r17244: There were several error paths where NT_PRINTER_INFO_LEVEL
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobdb098e74bec2307799d7bef125fffae8ca62ec51
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 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
70 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
73 /* API table for Xcv Monitor functions */
75 struct xcv_api_table {
76 const char *name;
77 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
81 /* translate between internal status numbers and NT status numbers */
82 static int nt_printj_status(int v)
84 switch (v) {
85 case LPQ_QUEUED:
86 return 0;
87 case LPQ_PAUSED:
88 return JOB_STATUS_PAUSED;
89 case LPQ_SPOOLING:
90 return JOB_STATUS_SPOOLING;
91 case LPQ_PRINTING:
92 return JOB_STATUS_PRINTING;
93 case LPQ_ERROR:
94 return JOB_STATUS_ERROR;
95 case LPQ_DELETING:
96 return JOB_STATUS_DELETING;
97 case LPQ_OFFLINE:
98 return JOB_STATUS_OFFLINE;
99 case LPQ_PAPEROUT:
100 return JOB_STATUS_PAPEROUT;
101 case LPQ_PRINTED:
102 return JOB_STATUS_PRINTED;
103 case LPQ_DELETED:
104 return JOB_STATUS_DELETED;
105 case LPQ_BLOCKED:
106 return JOB_STATUS_BLOCKED;
107 case LPQ_USER_INTERVENTION:
108 return JOB_STATUS_USER_INTERVENTION;
110 return 0;
113 static int nt_printq_status(int v)
115 switch (v) {
116 case LPQ_PAUSED:
117 return PRINTER_STATUS_PAUSED;
118 case LPQ_QUEUED:
119 case LPQ_SPOOLING:
120 case LPQ_PRINTING:
121 return 0;
123 return 0;
126 /****************************************************************************
127 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
128 ****************************************************************************/
130 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
132 if (*pp == NULL)
133 return;
135 SAFE_FREE((*pp)->ctr.type);
136 SAFE_FREE(*pp);
139 /***************************************************************************
140 Disconnect from the client
141 ****************************************************************************/
143 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
145 WERROR result;
148 * Tell the specific printing tdb we no longer want messages for this printer
149 * by deregistering our PID.
152 if (!print_notify_deregister_pid(snum))
153 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
155 /* weird if the test succeds !!! */
156 if (smb_connections==0) {
157 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
158 return;
161 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
163 if (!W_ERROR_IS_OK(result))
164 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
165 dos_errstr(result)));
167 /* if it's the last connection, deconnect the IPC$ share */
168 if (smb_connections==1) {
170 cli_shutdown( notify_cli_pipe->cli );
171 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
173 message_deregister(MSG_PRINTER_NOTIFY2);
175 /* Tell the connections db we're no longer interested in
176 * printer notify messages. */
178 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
181 smb_connections--;
184 /****************************************************************************
185 Functions to free a printer entry datastruct.
186 ****************************************************************************/
188 static void free_printer_entry(void *ptr)
190 Printer_entry *Printer = (Printer_entry *)ptr;
192 if (Printer->notify.client_connected==True) {
193 int snum = -1;
195 if ( Printer->printer_type == SPLHND_SERVER) {
196 snum = -1;
197 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
198 } else if (Printer->printer_type == SPLHND_PRINTER) {
199 snum = print_queue_snum(Printer->sharename);
200 if (snum != -1)
201 srv_spoolss_replycloseprinter(snum,
202 &Printer->notify.client_hnd);
206 Printer->notify.flags=0;
207 Printer->notify.options=0;
208 Printer->notify.localmachine[0]='\0';
209 Printer->notify.printerlocal=0;
210 free_spool_notify_option(&Printer->notify.option);
211 Printer->notify.option=NULL;
212 Printer->notify.client_connected=False;
214 free_nt_devicemode( &Printer->nt_devmode );
215 free_a_printer( &Printer->printer_info, 2 );
217 talloc_destroy( Printer->ctx );
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list, Printer);
222 SAFE_FREE(Printer);
225 /****************************************************************************
226 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
227 ****************************************************************************/
229 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
231 SPOOL_NOTIFY_OPTION *new_sp = NULL;
233 if (!sp)
234 return NULL;
236 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
237 if (!new_sp)
238 return NULL;
240 *new_sp = *sp;
242 if (sp->ctr.count) {
243 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
245 if (!new_sp->ctr.type) {
246 SAFE_FREE(new_sp);
247 return NULL;
251 return new_sp;
254 /****************************************************************************
255 find printer index by handle
256 ****************************************************************************/
258 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
260 Printer_entry *find_printer = NULL;
262 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
263 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
264 return NULL;
267 return find_printer;
270 /****************************************************************************
271 Close printer index by handle.
272 ****************************************************************************/
274 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
276 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
278 if (!Printer) {
279 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
280 return False;
283 close_policy_hnd(p, hnd);
285 return True;
288 /****************************************************************************
289 Delete a printer given a handle.
290 ****************************************************************************/
291 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
293 char *cmd = lp_deleteprinter_cmd();
294 pstring command;
295 int ret;
296 SE_PRIV se_printop = SE_PRINT_OPERATOR;
297 BOOL is_print_op = False;
299 /* can't fail if we don't try */
301 if ( !*cmd )
302 return WERR_OK;
304 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
306 if ( token )
307 is_print_op = user_has_privileges( token, &se_printop );
309 DEBUG(10,("Running [%s]\n", command));
311 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
313 if ( is_print_op )
314 become_root();
316 if ( (ret = smbrun(command, NULL)) == 0 ) {
317 /* Tell everyone we updated smb.conf. */
318 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
321 if ( is_print_op )
322 unbecome_root();
324 /********** END SePrintOperatorPrivlege BLOCK **********/
326 DEBUGADD(10,("returned [%d]\n", ret));
328 if (ret != 0)
329 return WERR_BADFID; /* What to return here? */
331 /* go ahead and re-read the services immediately */
332 reload_services( False );
334 if ( !share_defined( sharename ) )
335 return WERR_ACCESS_DENIED;
337 return WERR_OK;
340 /****************************************************************************
341 Delete a printer given a handle.
342 ****************************************************************************/
344 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
346 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
348 if (!Printer) {
349 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
350 return WERR_BADFID;
354 * It turns out that Windows allows delete printer on a handle
355 * opened by an admin user, then used on a pipe handle created
356 * by an anonymous user..... but they're working on security.... riiight !
357 * JRA.
360 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
361 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
362 return WERR_ACCESS_DENIED;
365 /* this does not need a become root since the access check has been
366 done on the handle already */
368 if (del_a_printer( Printer->sharename ) != 0) {
369 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
370 return WERR_BADFID;
373 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
376 /****************************************************************************
377 Return the snum of a printer corresponding to an handle.
378 ****************************************************************************/
380 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
382 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
384 if (!Printer) {
385 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
386 return False;
389 switch (Printer->printer_type) {
390 case SPLHND_PRINTER:
391 DEBUG(4,("short name:%s\n", Printer->sharename));
392 *number = print_queue_snum(Printer->sharename);
393 return (*number != -1);
394 case SPLHND_SERVER:
395 return False;
396 default:
397 return False;
401 /****************************************************************************
402 Set printer handle type.
403 Check if it's \\server or \\server\printer
404 ****************************************************************************/
406 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
408 DEBUG(3,("Setting printer type=%s\n", handlename));
410 if ( strlen(handlename) < 3 ) {
411 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
412 return False;
415 /* it's a print server */
416 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
417 DEBUGADD(4,("Printer is a print server\n"));
418 Printer->printer_type = SPLHND_SERVER;
420 /* it's a printer (set_printer_hnd_name() will handle port monitors */
421 else {
422 DEBUGADD(4,("Printer is a printer\n"));
423 Printer->printer_type = SPLHND_PRINTER;
426 return True;
429 /****************************************************************************
430 Set printer handle name.. Accept names like \\server, \\server\printer,
431 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
432 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
433 XcvDataPort() interface.
434 ****************************************************************************/
436 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
438 int snum;
439 int n_services=lp_numservices();
440 char *aprinter, *printername;
441 const char *servername;
442 fstring sname;
443 BOOL found=False;
444 NT_PRINTER_INFO_LEVEL *printer = NULL;
445 WERROR result;
447 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
449 aprinter = handlename;
450 if ( *handlename == '\\' ) {
451 servername = handlename + 2;
452 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
453 *aprinter = '\0';
454 aprinter++;
457 else {
458 servername = "";
461 /* save the servername to fill in replies on this handle */
463 if ( !is_myname_or_ipaddr( servername ) )
464 return False;
466 fstrcpy( Printer->servername, servername );
468 if ( Printer->printer_type == SPLHND_SERVER )
469 return True;
471 if ( Printer->printer_type != SPLHND_PRINTER )
472 return False;
474 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
476 /* check for the Port Monitor Interface */
478 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
479 Printer->printer_type = SPLHND_PORTMON_TCP;
480 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
481 found = True;
483 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
484 Printer->printer_type = SPLHND_PORTMON_LOCAL;
485 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
486 found = True;
489 /* Search all sharenames first as this is easier than pulling
490 the printer_info_2 off of disk. Don't use find_service() since
491 that calls out to map_username() */
493 /* do another loop to look for printernames */
495 for (snum=0; !found && snum<n_services; snum++) {
497 /* no point going on if this is not a printer */
499 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
500 continue;
502 fstrcpy(sname, lp_servicename(snum));
503 if ( strequal( aprinter, sname ) ) {
504 found = True;
505 break;
508 /* no point looking up the printer object if
509 we aren't allowing printername != sharename */
511 if ( lp_force_printername(snum) )
512 continue;
514 fstrcpy(sname, lp_servicename(snum));
516 printer = NULL;
517 result = get_a_printer( NULL, &printer, 2, sname );
518 if ( !W_ERROR_IS_OK(result) ) {
519 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
520 sname, dos_errstr(result)));
521 continue;
524 /* printername is always returned as \\server\printername */
525 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
526 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
527 printer->info_2->printername));
528 free_a_printer( &printer, 2);
529 continue;
532 printername++;
534 if ( strequal(printername, aprinter) ) {
535 free_a_printer( &printer, 2);
536 found = True;
537 break;
540 DEBUGADD(10, ("printername: %s\n", printername));
542 free_a_printer( &printer, 2);
545 free_a_printer( &printer, 2);
547 if ( !found ) {
548 DEBUGADD(4,("Printer not found\n"));
549 return False;
552 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
554 fstrcpy(Printer->sharename, sname);
556 return True;
559 /****************************************************************************
560 Find first available printer slot. creates a printer handle for you.
561 ****************************************************************************/
563 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
565 Printer_entry *new_printer;
567 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
569 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
570 return False;
572 ZERO_STRUCTP(new_printer);
574 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
575 SAFE_FREE(new_printer);
576 return False;
579 /* Add to the internal list. */
580 DLIST_ADD(printers_list, new_printer);
582 new_printer->notify.option=NULL;
584 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
585 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
586 close_printer_handle(p, hnd);
587 return False;
590 if (!set_printer_hnd_printertype(new_printer, name)) {
591 close_printer_handle(p, hnd);
592 return False;
595 if (!set_printer_hnd_name(new_printer, name)) {
596 close_printer_handle(p, hnd);
597 return False;
600 new_printer->access_granted = access_granted;
602 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
604 return True;
607 /***************************************************************************
608 check to see if the client motify handle is monitoring the notification
609 given by (notify_type, notify_field).
610 **************************************************************************/
612 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
613 uint16 notify_field)
615 return True;
618 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
619 uint16 notify_field)
621 SPOOL_NOTIFY_OPTION *option = p->notify.option;
622 uint32 i, j;
625 * Flags should always be zero when the change notify
626 * is registered by the client's spooler. A user Win32 app
627 * might use the flags though instead of the NOTIFY_OPTION_INFO
628 * --jerry
631 if (!option) {
632 return False;
635 if (p->notify.flags)
636 return is_monitoring_event_flags(
637 p->notify.flags, notify_type, notify_field);
639 for (i = 0; i < option->count; i++) {
641 /* Check match for notify_type */
643 if (option->ctr.type[i].type != notify_type)
644 continue;
646 /* Check match for field */
648 for (j = 0; j < option->ctr.type[i].count; j++) {
649 if (option->ctr.type[i].fields[j] == notify_field) {
650 return True;
655 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
656 p->servername, p->sharename, notify_type, notify_field));
658 return False;
661 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
663 static void notify_one_value(struct spoolss_notify_msg *msg,
664 SPOOL_NOTIFY_INFO_DATA *data,
665 TALLOC_CTX *mem_ctx)
667 data->notify_data.value[0] = msg->notify.value[0];
668 data->notify_data.value[1] = 0;
671 static void notify_string(struct spoolss_notify_msg *msg,
672 SPOOL_NOTIFY_INFO_DATA *data,
673 TALLOC_CTX *mem_ctx)
675 UNISTR2 unistr;
677 /* The length of the message includes the trailing \0 */
679 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
681 data->notify_data.data.length = msg->len * 2;
682 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
684 if (!data->notify_data.data.string) {
685 data->notify_data.data.length = 0;
686 return;
689 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
692 static void notify_system_time(struct spoolss_notify_msg *msg,
693 SPOOL_NOTIFY_INFO_DATA *data,
694 TALLOC_CTX *mem_ctx)
696 SYSTEMTIME systime;
697 prs_struct ps;
699 if (msg->len != sizeof(time_t)) {
700 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
701 msg->len));
702 return;
705 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
706 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
707 return;
710 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
711 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
712 prs_mem_free(&ps);
713 return;
716 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
717 prs_mem_free(&ps);
718 return;
721 data->notify_data.data.length = prs_offset(&ps);
722 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
723 if (!data->notify_data.data.string) {
724 prs_mem_free(&ps);
725 return;
728 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
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 = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
916 return ctr->num_groups;
919 /***********************************************************************
920 Send a change notication message on all handles which have a call
921 back registered
922 **********************************************************************/
924 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
926 Printer_entry *p;
927 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
928 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
929 SPOOLSS_NOTIFY_MSG *messages;
930 int sending_msg_count;
932 if ( !msg_group ) {
933 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
934 return;
937 messages = msg_group->msgs;
939 if ( !messages ) {
940 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
941 return;
944 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
946 /* loop over all printers */
948 for (p = printers_list; p; p = p->next) {
949 SPOOL_NOTIFY_INFO_DATA *data;
950 uint32 data_len = 0;
951 uint32 id;
952 int i;
954 /* Is there notification on this handle? */
956 if ( !p->notify.client_connected )
957 continue;
959 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
961 /* For this printer? Print servers always receive
962 notifications. */
964 if ( ( p->printer_type == SPLHND_PRINTER ) &&
965 ( !strequal(msg_group->printername, p->sharename) ) )
966 continue;
968 DEBUG(10,("Our printer\n"));
970 /* allocate the max entries possible */
972 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
973 if (!data) {
974 return;
977 ZERO_STRUCTP(data);
979 /* build the array of change notifications */
981 sending_msg_count = 0;
983 for ( i=0; i<msg_group->num_msgs; i++ ) {
984 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
986 /* Are we monitoring this event? */
988 if (!is_monitoring_event(p, msg->type, msg->field))
989 continue;
991 sending_msg_count++;
994 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
995 msg->type, msg->field, p->sharename));
998 * if the is a printer notification handle and not a job notification
999 * type, then set the id to 0. Other wise just use what was specified
1000 * in the message.
1002 * When registering change notification on a print server handle
1003 * we always need to send back the id (snum) matching the printer
1004 * for which the change took place. For change notify registered
1005 * on a printer handle, this does not matter and the id should be 0.
1007 * --jerry
1010 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1011 id = 0;
1012 else
1013 id = msg->id;
1016 /* Convert unix jobid to smb jobid */
1018 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1019 id = sysjob_to_jobid(msg->id);
1021 if (id == -1) {
1022 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1023 goto done;
1027 construct_info_data( &data[data_len], msg->type, msg->field, id );
1029 switch(msg->type) {
1030 case PRINTER_NOTIFY_TYPE:
1031 if ( printer_notify_table[msg->field].fn )
1032 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1033 break;
1035 case JOB_NOTIFY_TYPE:
1036 if ( job_notify_table[msg->field].fn )
1037 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1038 break;
1040 default:
1041 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1042 goto done;
1045 data_len++;
1048 if ( sending_msg_count ) {
1049 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1050 data_len, data, p->notify.change, 0 );
1054 done:
1055 DEBUG(8,("send_notify2_changes: Exit...\n"));
1056 return;
1059 /***********************************************************************
1060 **********************************************************************/
1062 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1065 uint32 tv_sec, tv_usec;
1066 size_t offset = 0;
1068 /* Unpack message */
1070 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1071 msg->printer);
1073 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1074 &tv_sec, &tv_usec,
1075 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1077 if (msg->len == 0)
1078 tdb_unpack((char *)buf + offset, len - offset, "dd",
1079 &msg->notify.value[0], &msg->notify.value[1]);
1080 else
1081 tdb_unpack((char *)buf + offset, len - offset, "B",
1082 &msg->len, &msg->notify.data);
1084 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1085 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1087 tv->tv_sec = tv_sec;
1088 tv->tv_usec = tv_usec;
1090 if (msg->len == 0)
1091 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1092 msg->notify.value[1]));
1093 else
1094 dump_data(3, msg->notify.data, msg->len);
1096 return True;
1099 /********************************************************************
1100 Receive a notify2 message list
1101 ********************************************************************/
1103 static void receive_notify2_message_list(int msg_type, struct process_id src,
1104 void *msg, size_t len)
1106 size_t msg_count, i;
1107 char *buf = (char *)msg;
1108 char *msg_ptr;
1109 size_t msg_len;
1110 SPOOLSS_NOTIFY_MSG notify;
1111 SPOOLSS_NOTIFY_MSG_CTR messages;
1112 int num_groups;
1114 if (len < 4) {
1115 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1116 return;
1119 msg_count = IVAL(buf, 0);
1120 msg_ptr = buf + 4;
1122 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1124 if (msg_count == 0) {
1125 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1126 return;
1129 /* initialize the container */
1131 ZERO_STRUCT( messages );
1132 notify_msg_ctr_init( &messages );
1135 * build message groups for each printer identified
1136 * in a change_notify msg. Remember that a PCN message
1137 * includes the handle returned for the srv_spoolss_replyopenprinter()
1138 * call. Therefore messages are grouped according to printer handle.
1141 for ( i=0; i<msg_count; i++ ) {
1142 struct timeval msg_tv;
1144 if (msg_ptr + 4 - buf > len) {
1145 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1146 return;
1149 msg_len = IVAL(msg_ptr,0);
1150 msg_ptr += 4;
1152 if (msg_ptr + msg_len - buf > len) {
1153 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1154 return;
1157 /* unpack messages */
1159 ZERO_STRUCT( notify );
1160 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1161 msg_ptr += msg_len;
1163 /* add to correct list in container */
1165 notify_msg_ctr_addmsg( &messages, &notify );
1167 /* free memory that might have been allocated by notify2_unpack_msg() */
1169 if ( notify.len != 0 )
1170 SAFE_FREE( notify.notify.data );
1173 /* process each group of messages */
1175 num_groups = notify_msg_ctr_numgroups( &messages );
1176 for ( i=0; i<num_groups; i++ )
1177 send_notify2_changes( &messages, i );
1180 /* cleanup */
1182 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1184 notify_msg_ctr_destroy( &messages );
1186 return;
1189 /********************************************************************
1190 Send a message to ourself about new driver being installed
1191 so we can upgrade the information for each printer bound to this
1192 driver
1193 ********************************************************************/
1195 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1197 int len = strlen(drivername);
1199 if (!len)
1200 return False;
1202 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1203 drivername));
1205 message_send_pid(pid_to_procid(sys_getpid()),
1206 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1208 return True;
1211 /**********************************************************************
1212 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1213 over all printers, upgrading ones as necessary
1214 **********************************************************************/
1216 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1218 fstring drivername;
1219 int snum;
1220 int n_services = lp_numservices();
1222 len = MIN(len,sizeof(drivername)-1);
1223 strncpy(drivername, buf, len);
1225 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1227 /* Iterate the printer list */
1229 for (snum=0; snum<n_services; snum++)
1231 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1233 WERROR result;
1234 NT_PRINTER_INFO_LEVEL *printer = NULL;
1236 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1237 if (!W_ERROR_IS_OK(result))
1238 continue;
1240 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1242 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1244 /* all we care about currently is the change_id */
1246 result = mod_a_printer(printer, 2);
1247 if (!W_ERROR_IS_OK(result)) {
1248 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1249 dos_errstr(result)));
1253 free_a_printer(&printer, 2);
1257 /* all done */
1260 /********************************************************************
1261 Update the cache for all printq's with a registered client
1262 connection
1263 ********************************************************************/
1265 void update_monitored_printq_cache( void )
1267 Printer_entry *printer = printers_list;
1268 int snum;
1270 /* loop through all printers and update the cache where
1271 client_connected == True */
1272 while ( printer )
1274 if ( (printer->printer_type == SPLHND_PRINTER)
1275 && printer->notify.client_connected )
1277 snum = print_queue_snum(printer->sharename);
1278 print_queue_status( snum, NULL, NULL );
1281 printer = printer->next;
1284 return;
1286 /********************************************************************
1287 Send a message to ourself about new driver being installed
1288 so we can upgrade the information for each printer bound to this
1289 driver
1290 ********************************************************************/
1292 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1294 int len = strlen(drivername);
1296 if (!len)
1297 return False;
1299 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1300 drivername));
1302 message_send_pid(pid_to_procid(sys_getpid()),
1303 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1305 return True;
1308 /**********************************************************************
1309 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1310 over all printers, resetting printer data as neessary
1311 **********************************************************************/
1313 void reset_all_printerdata(int msg_type, struct process_id src,
1314 void *buf, size_t len)
1316 fstring drivername;
1317 int snum;
1318 int n_services = lp_numservices();
1320 len = MIN( len, sizeof(drivername)-1 );
1321 strncpy( drivername, buf, len );
1323 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1325 /* Iterate the printer list */
1327 for ( snum=0; snum<n_services; snum++ )
1329 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1331 WERROR result;
1332 NT_PRINTER_INFO_LEVEL *printer = NULL;
1334 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1335 if ( !W_ERROR_IS_OK(result) )
1336 continue;
1339 * if the printer is bound to the driver,
1340 * then reset to the new driver initdata
1343 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1345 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1347 if ( !set_driver_init(printer, 2) ) {
1348 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1349 printer->info_2->printername, printer->info_2->drivername));
1352 result = mod_a_printer( printer, 2 );
1353 if ( !W_ERROR_IS_OK(result) ) {
1354 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1355 get_dos_error_msg(result)));
1359 free_a_printer( &printer, 2 );
1363 /* all done */
1365 return;
1368 /********************************************************************
1369 Copy routines used by convert_to_openprinterex()
1370 *******************************************************************/
1372 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1374 DEVICEMODE *d;
1375 int len;
1377 if (!devmode)
1378 return NULL;
1380 DEBUG (8,("dup_devmode\n"));
1382 /* bulk copy first */
1384 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1385 if (!d)
1386 return NULL;
1388 /* dup the pointer members separately */
1390 len = unistrlen(devmode->devicename.buffer);
1391 if (len != -1) {
1392 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1393 if (!d->devicename.buffer) {
1394 return NULL;
1396 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1397 return NULL;
1401 len = unistrlen(devmode->formname.buffer);
1402 if (len != -1) {
1403 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1404 if (!d->devicename.buffer) {
1405 return NULL;
1407 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1408 return NULL;
1411 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1412 if (!d->dev_private) {
1413 return NULL;
1415 return d;
1418 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1420 if (!new_ctr || !ctr)
1421 return;
1423 DEBUG(8,("copy_devmode_ctr\n"));
1425 new_ctr->size = ctr->size;
1426 new_ctr->devmode_ptr = ctr->devmode_ptr;
1428 if(ctr->devmode_ptr)
1429 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1432 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1434 if (!new_def || !def)
1435 return;
1437 DEBUG(8,("copy_printer_defaults\n"));
1439 new_def->datatype_ptr = def->datatype_ptr;
1441 if (def->datatype_ptr)
1442 copy_unistr2(&new_def->datatype, &def->datatype);
1444 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1446 new_def->access_required = def->access_required;
1449 /********************************************************************
1450 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1451 * SPOOL_Q_OPEN_PRINTER_EX structure
1452 ********************************************************************/
1454 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1456 if (!q_u_ex || !q_u)
1457 return WERR_OK;
1459 DEBUG(8,("convert_to_openprinterex\n"));
1461 if ( q_u->printername ) {
1462 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1463 if (q_u_ex->printername == NULL)
1464 return WERR_NOMEM;
1465 copy_unistr2(q_u_ex->printername, q_u->printername);
1468 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1470 return WERR_OK;
1473 /********************************************************************
1474 * spoolss_open_printer
1476 * called from the spoolss dispatcher
1477 ********************************************************************/
1479 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1481 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1482 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1484 if (!q_u || !r_u)
1485 return WERR_NOMEM;
1487 ZERO_STRUCT(q_u_ex);
1488 ZERO_STRUCT(r_u_ex);
1490 /* convert the OpenPrinter() call to OpenPrinterEx() */
1492 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1493 if (!W_ERROR_IS_OK(r_u_ex.status))
1494 return r_u_ex.status;
1496 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1498 /* convert back to OpenPrinter() */
1500 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1502 return r_u->status;
1505 /********************************************************************
1506 ********************************************************************/
1508 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1510 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1511 POLICY_HND *handle = &r_u->handle;
1513 fstring name;
1514 int snum;
1515 Printer_entry *Printer=NULL;
1517 if ( !q_u->printername )
1518 return WERR_INVALID_PRINTER_NAME;
1520 /* some sanity check because you can open a printer or a print server */
1521 /* aka: \\server\printer or \\server */
1523 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1525 DEBUGADD(3,("checking name: %s\n",name));
1527 if (!open_printer_hnd(p, handle, name, 0))
1528 return WERR_INVALID_PRINTER_NAME;
1530 Printer=find_printer_index_by_hnd(p, handle);
1531 if ( !Printer ) {
1532 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1533 "handle we created for printer %s\n", name ));
1534 close_printer_handle(p,handle);
1535 return WERR_INVALID_PRINTER_NAME;
1539 * First case: the user is opening the print server:
1541 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1542 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1544 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1545 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1546 * or if the user is listed in the smb.conf printer admin parameter.
1548 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1549 * client view printer folder, but does not show the MSAPW.
1551 * Note: this test needs code to check access rights here too. Jeremy
1552 * could you look at this?
1554 * Second case: the user is opening a printer:
1555 * NT doesn't let us connect to a printer if the connecting user
1556 * doesn't have print permission.
1558 * Third case: user is opening a Port Monitor
1559 * access checks same as opening a handle to the print server.
1562 switch (Printer->printer_type )
1564 case SPLHND_SERVER:
1565 case SPLHND_PORTMON_TCP:
1566 case SPLHND_PORTMON_LOCAL:
1567 /* Printserver handles use global struct... */
1569 snum = -1;
1571 /* Map standard access rights to object specific access rights */
1573 se_map_standard(&printer_default->access_required,
1574 &printserver_std_mapping);
1576 /* Deny any object specific bits that don't apply to print
1577 servers (i.e printer and job specific bits) */
1579 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1581 if (printer_default->access_required &
1582 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1583 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1584 close_printer_handle(p, handle);
1585 return WERR_ACCESS_DENIED;
1588 /* Allow admin access */
1590 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1592 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1594 if (!lp_ms_add_printer_wizard()) {
1595 close_printer_handle(p, handle);
1596 return WERR_ACCESS_DENIED;
1599 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1600 and not a printer admin, then fail */
1602 if ((p->pipe_user.ut.uid != 0) &&
1603 !user_has_privileges(p->pipe_user.nt_user_token,
1604 &se_printop ) &&
1605 !token_contains_name_in_list(
1606 uidtoname(p->pipe_user.ut.uid), NULL,
1607 p->pipe_user.nt_user_token,
1608 lp_printer_admin(snum))) {
1609 close_printer_handle(p, handle);
1610 return WERR_ACCESS_DENIED;
1613 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1615 else
1617 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1620 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1621 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1623 /* We fall through to return WERR_OK */
1624 break;
1626 case SPLHND_PRINTER:
1627 /* NT doesn't let us connect to a printer if the connecting user
1628 doesn't have print permission. */
1630 if (!get_printer_snum(p, handle, &snum)) {
1631 close_printer_handle(p, handle);
1632 return WERR_BADFID;
1635 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1637 /* map an empty access mask to the minimum access mask */
1638 if (printer_default->access_required == 0x0)
1639 printer_default->access_required = PRINTER_ACCESS_USE;
1642 * If we are not serving the printer driver for this printer,
1643 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1644 * will keep NT clients happy --jerry
1647 if (lp_use_client_driver(snum)
1648 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1650 printer_default->access_required = PRINTER_ACCESS_USE;
1653 /* check smb.conf parameters and the the sec_desc */
1655 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1656 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1657 return WERR_ACCESS_DENIED;
1660 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1661 p->pipe_user.nt_user_token, snum) ||
1662 !print_access_check(&p->pipe_user, snum,
1663 printer_default->access_required)) {
1664 DEBUG(3, ("access DENIED for printer open\n"));
1665 close_printer_handle(p, handle);
1666 return WERR_ACCESS_DENIED;
1669 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1670 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1671 close_printer_handle(p, handle);
1672 return WERR_ACCESS_DENIED;
1675 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1676 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1677 else
1678 printer_default->access_required = PRINTER_ACCESS_USE;
1680 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1681 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1683 break;
1685 default:
1686 /* sanity check to prevent programmer error */
1687 return WERR_BADFID;
1690 Printer->access_granted = printer_default->access_required;
1693 * If the client sent a devmode in the OpenPrinter() call, then
1694 * save it here in case we get a job submission on this handle
1697 if ( (Printer->printer_type != SPLHND_SERVER)
1698 && q_u->printer_default.devmode_cont.devmode_ptr )
1700 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1701 &Printer->nt_devmode );
1704 #if 0 /* JERRY -- I'm doubtful this is really effective */
1705 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1706 optimization in Windows 2000 clients --jerry */
1708 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1709 && (RA_WIN2K == get_remote_arch()) )
1711 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1712 sys_usleep( 500000 );
1714 #endif
1716 return WERR_OK;
1719 /****************************************************************************
1720 ****************************************************************************/
1722 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1723 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1725 BOOL ret;
1727 switch (level) {
1728 case 2:
1729 /* allocate memory if needed. Messy because
1730 convert_printer_info is used to update an existing
1731 printer or build a new one */
1733 if ( !printer->info_2 ) {
1734 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1735 if ( !printer->info_2 ) {
1736 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1737 return False;
1741 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1742 printer->info_2->setuptime = time(NULL);
1744 return ret;
1747 return False;
1750 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1751 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1753 BOOL result = True;
1755 switch (level) {
1756 case 3:
1757 printer->info_3=NULL;
1758 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1759 result = False;
1760 break;
1761 case 6:
1762 printer->info_6=NULL;
1763 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1764 result = False;
1765 break;
1766 default:
1767 break;
1770 return result;
1773 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1774 NT_DEVICEMODE **pp_nt_devmode)
1776 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1779 * Ensure nt_devmode is a valid pointer
1780 * as we will be overwriting it.
1783 if (nt_devmode == NULL) {
1784 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1785 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1786 return False;
1789 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1790 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1792 nt_devmode->specversion=devmode->specversion;
1793 nt_devmode->driverversion=devmode->driverversion;
1794 nt_devmode->size=devmode->size;
1795 nt_devmode->fields=devmode->fields;
1796 nt_devmode->orientation=devmode->orientation;
1797 nt_devmode->papersize=devmode->papersize;
1798 nt_devmode->paperlength=devmode->paperlength;
1799 nt_devmode->paperwidth=devmode->paperwidth;
1800 nt_devmode->scale=devmode->scale;
1801 nt_devmode->copies=devmode->copies;
1802 nt_devmode->defaultsource=devmode->defaultsource;
1803 nt_devmode->printquality=devmode->printquality;
1804 nt_devmode->color=devmode->color;
1805 nt_devmode->duplex=devmode->duplex;
1806 nt_devmode->yresolution=devmode->yresolution;
1807 nt_devmode->ttoption=devmode->ttoption;
1808 nt_devmode->collate=devmode->collate;
1810 nt_devmode->logpixels=devmode->logpixels;
1811 nt_devmode->bitsperpel=devmode->bitsperpel;
1812 nt_devmode->pelswidth=devmode->pelswidth;
1813 nt_devmode->pelsheight=devmode->pelsheight;
1814 nt_devmode->displayflags=devmode->displayflags;
1815 nt_devmode->displayfrequency=devmode->displayfrequency;
1816 nt_devmode->icmmethod=devmode->icmmethod;
1817 nt_devmode->icmintent=devmode->icmintent;
1818 nt_devmode->mediatype=devmode->mediatype;
1819 nt_devmode->dithertype=devmode->dithertype;
1820 nt_devmode->reserved1=devmode->reserved1;
1821 nt_devmode->reserved2=devmode->reserved2;
1822 nt_devmode->panningwidth=devmode->panningwidth;
1823 nt_devmode->panningheight=devmode->panningheight;
1826 * Only change private and driverextra if the incoming devmode
1827 * has a new one. JRA.
1830 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1831 SAFE_FREE(nt_devmode->nt_dev_private);
1832 nt_devmode->driverextra=devmode->driverextra;
1833 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1834 return False;
1835 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1838 *pp_nt_devmode = nt_devmode;
1840 return True;
1843 /********************************************************************
1844 * _spoolss_enddocprinter_internal.
1845 ********************************************************************/
1847 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1849 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1850 int snum;
1852 if (!Printer) {
1853 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1854 return WERR_BADFID;
1857 if (!get_printer_snum(p, handle, &snum))
1858 return WERR_BADFID;
1860 Printer->document_started=False;
1861 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1862 /* error codes unhandled so far ... */
1864 return WERR_OK;
1867 /********************************************************************
1868 * api_spoolss_closeprinter
1869 ********************************************************************/
1871 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1873 POLICY_HND *handle = &q_u->handle;
1875 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1877 if (Printer && Printer->document_started)
1878 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1880 if (!close_printer_handle(p, handle))
1881 return WERR_BADFID;
1883 /* clear the returned printer handle. Observed behavior
1884 from Win2k server. Don't think this really matters.
1885 Previous code just copied the value of the closed
1886 handle. --jerry */
1888 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1890 return WERR_OK;
1893 /********************************************************************
1894 * api_spoolss_deleteprinter
1896 ********************************************************************/
1898 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1900 POLICY_HND *handle = &q_u->handle;
1901 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1902 WERROR result;
1904 if (Printer && Printer->document_started)
1905 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1907 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1909 result = delete_printer_handle(p, handle);
1911 update_c_setprinter(False);
1913 return result;
1916 /*******************************************************************
1917 * static function to lookup the version id corresponding to an
1918 * long architecture string
1919 ******************************************************************/
1921 static int get_version_id (char * arch)
1923 int i;
1924 struct table_node archi_table[]= {
1926 {"Windows 4.0", "WIN40", 0 },
1927 {"Windows NT x86", "W32X86", 2 },
1928 {"Windows NT R4000", "W32MIPS", 2 },
1929 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1930 {"Windows NT PowerPC", "W32PPC", 2 },
1931 {"Windows IA64", "IA64", 3 },
1932 {"Windows x64", "x64", 3 },
1933 {NULL, "", -1 }
1936 for (i=0; archi_table[i].long_archi != NULL; i++)
1938 if (strcmp(arch, archi_table[i].long_archi) == 0)
1939 return (archi_table[i].version);
1942 return -1;
1945 /********************************************************************
1946 * _spoolss_deleteprinterdriver
1947 ********************************************************************/
1949 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1951 fstring driver;
1952 fstring arch;
1953 NT_PRINTER_DRIVER_INFO_LEVEL info;
1954 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1955 int version;
1956 WERROR status;
1957 WERROR status_win2k = WERR_ACCESS_DENIED;
1958 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1960 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1961 and not a printer admin, then fail */
1963 if ( (p->pipe_user.ut.uid != 0)
1964 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1965 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1966 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1968 return WERR_ACCESS_DENIED;
1971 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1972 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1974 /* check that we have a valid driver name first */
1976 if ((version=get_version_id(arch)) == -1)
1977 return WERR_INVALID_ENVIRONMENT;
1979 ZERO_STRUCT(info);
1980 ZERO_STRUCT(info_win2k);
1982 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1984 /* try for Win2k driver if "Windows NT x86" */
1986 if ( version == 2 ) {
1987 version = 3;
1988 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1989 status = WERR_UNKNOWN_PRINTER_DRIVER;
1990 goto done;
1993 /* otherwise it was a failure */
1994 else {
1995 status = WERR_UNKNOWN_PRINTER_DRIVER;
1996 goto done;
2001 if (printer_driver_in_use(info.info_3)) {
2002 status = WERR_PRINTER_DRIVER_IN_USE;
2003 goto done;
2006 if ( version == 2 )
2008 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2010 /* if we get to here, we now have 2 driver info structures to remove */
2011 /* remove the Win2k driver first*/
2013 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2014 free_a_printer_driver( info_win2k, 3 );
2016 /* this should not have failed---if it did, report to client */
2017 if ( !W_ERROR_IS_OK(status_win2k) )
2019 status = status_win2k;
2020 goto done;
2025 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2027 /* if at least one of the deletes succeeded return OK */
2029 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2030 status = WERR_OK;
2032 done:
2033 free_a_printer_driver( info, 3 );
2035 return status;
2038 /********************************************************************
2039 * spoolss_deleteprinterdriverex
2040 ********************************************************************/
2042 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2044 fstring driver;
2045 fstring arch;
2046 NT_PRINTER_DRIVER_INFO_LEVEL info;
2047 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2048 int version;
2049 uint32 flags = q_u->delete_flags;
2050 BOOL delete_files;
2051 WERROR status;
2052 WERROR status_win2k = WERR_ACCESS_DENIED;
2053 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2055 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2056 and not a printer admin, then fail */
2058 if ( (p->pipe_user.ut.uid != 0)
2059 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2060 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2061 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2063 return WERR_ACCESS_DENIED;
2066 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2067 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2069 /* check that we have a valid driver name first */
2070 if ((version=get_version_id(arch)) == -1) {
2071 /* this is what NT returns */
2072 return WERR_INVALID_ENVIRONMENT;
2075 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2076 version = q_u->version;
2078 ZERO_STRUCT(info);
2079 ZERO_STRUCT(info_win2k);
2081 status = get_a_printer_driver(&info, 3, driver, arch, version);
2083 if ( !W_ERROR_IS_OK(status) )
2086 * if the client asked for a specific version,
2087 * or this is something other than Windows NT x86,
2088 * then we've failed
2091 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2092 goto done;
2094 /* try for Win2k driver if "Windows NT x86" */
2096 version = 3;
2097 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2098 status = WERR_UNKNOWN_PRINTER_DRIVER;
2099 goto done;
2103 if ( printer_driver_in_use(info.info_3) ) {
2104 status = WERR_PRINTER_DRIVER_IN_USE;
2105 goto done;
2109 * we have a couple of cases to consider.
2110 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2111 * then the delete should fail if **any** files overlap with
2112 * other drivers
2113 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2114 * non-overlapping files
2115 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2116 * is set, the do not delete any files
2117 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2120 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2122 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2124 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2125 /* no idea of the correct error here */
2126 status = WERR_ACCESS_DENIED;
2127 goto done;
2131 /* also check for W32X86/3 if necessary; maybe we already have? */
2133 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2134 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2137 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2138 /* no idea of the correct error here */
2139 free_a_printer_driver( info_win2k, 3 );
2140 status = WERR_ACCESS_DENIED;
2141 goto done;
2144 /* if we get to here, we now have 2 driver info structures to remove */
2145 /* remove the Win2k driver first*/
2147 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2148 free_a_printer_driver( info_win2k, 3 );
2150 /* this should not have failed---if it did, report to client */
2152 if ( !W_ERROR_IS_OK(status_win2k) )
2153 goto done;
2157 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2159 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2160 status = WERR_OK;
2161 done:
2162 free_a_printer_driver( info, 3 );
2164 return status;
2168 /****************************************************************************
2169 Internal routine for retreiving printerdata
2170 ***************************************************************************/
2172 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2173 const char *key, const char *value, uint32 *type, uint8 **data,
2174 uint32 *needed, uint32 in_size )
2176 REGISTRY_VALUE *val;
2177 uint32 size;
2178 int data_len;
2180 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2181 return WERR_BADFILE;
2183 *type = regval_type( val );
2185 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2187 size = regval_size( val );
2189 /* copy the min(in_size, len) */
2191 if ( in_size ) {
2192 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2194 /* special case for 0 length values */
2195 if ( data_len ) {
2196 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2197 return WERR_NOMEM;
2199 else {
2200 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2201 return WERR_NOMEM;
2204 else
2205 *data = NULL;
2207 *needed = size;
2209 DEBUG(5,("get_printer_dataex: copy done\n"));
2211 return WERR_OK;
2214 /****************************************************************************
2215 Internal routine for removing printerdata
2216 ***************************************************************************/
2218 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2220 return delete_printer_data( printer->info_2, key, value );
2223 /****************************************************************************
2224 Internal routine for storing printerdata
2225 ***************************************************************************/
2227 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2228 uint32 type, uint8 *data, int real_len )
2230 /* the registry objects enforce uniqueness based on value name */
2232 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2235 /********************************************************************
2236 GetPrinterData on a printer server Handle.
2237 ********************************************************************/
2239 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2241 int i;
2243 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2245 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2246 *type = REG_DWORD;
2247 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2248 return WERR_NOMEM;
2249 *needed = 0x4;
2250 return WERR_OK;
2253 if (!StrCaseCmp(value, "BeepEnabled")) {
2254 *type = REG_DWORD;
2255 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2256 return WERR_NOMEM;
2257 SIVAL(*data, 0, 0x00);
2258 *needed = 0x4;
2259 return WERR_OK;
2262 if (!StrCaseCmp(value, "EventLog")) {
2263 *type = REG_DWORD;
2264 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2265 return WERR_NOMEM;
2266 /* formally was 0x1b */
2267 SIVAL(*data, 0, 0x0);
2268 *needed = 0x4;
2269 return WERR_OK;
2272 if (!StrCaseCmp(value, "NetPopup")) {
2273 *type = REG_DWORD;
2274 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2275 return WERR_NOMEM;
2276 SIVAL(*data, 0, 0x00);
2277 *needed = 0x4;
2278 return WERR_OK;
2281 if (!StrCaseCmp(value, "MajorVersion")) {
2282 *type = REG_DWORD;
2283 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2284 return WERR_NOMEM;
2286 /* Windows NT 4.0 seems to not allow uploading of drivers
2287 to a server that reports 0x3 as the MajorVersion.
2288 need to investigate more how Win2k gets around this .
2289 -- jerry */
2291 if ( RA_WINNT == get_remote_arch() )
2292 SIVAL(*data, 0, 2);
2293 else
2294 SIVAL(*data, 0, 3);
2296 *needed = 0x4;
2297 return WERR_OK;
2300 if (!StrCaseCmp(value, "MinorVersion")) {
2301 *type = REG_DWORD;
2302 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2303 return WERR_NOMEM;
2304 SIVAL(*data, 0, 0);
2305 *needed = 0x4;
2306 return WERR_OK;
2309 /* REG_BINARY
2310 * uint32 size = 0x114
2311 * uint32 major = 5
2312 * uint32 minor = [0|1]
2313 * uint32 build = [2195|2600]
2314 * extra unicode string = e.g. "Service Pack 3"
2316 if (!StrCaseCmp(value, "OSVersion")) {
2317 *type = REG_BINARY;
2318 *needed = 0x114;
2320 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2321 return WERR_NOMEM;
2323 SIVAL(*data, 0, *needed); /* size */
2324 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2325 SIVAL(*data, 8, 0);
2326 SIVAL(*data, 12, 2195); /* build */
2328 /* leave extra string empty */
2330 return WERR_OK;
2334 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2335 const char *string="C:\\PRINTERS";
2336 *type = REG_SZ;
2337 *needed = 2*(strlen(string)+1);
2338 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2339 return WERR_NOMEM;
2340 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2342 /* it's done by hand ready to go on the wire */
2343 for (i=0; i<strlen(string); i++) {
2344 (*data)[2*i]=string[i];
2345 (*data)[2*i+1]='\0';
2347 return WERR_OK;
2350 if (!StrCaseCmp(value, "Architecture")) {
2351 const char *string="Windows NT x86";
2352 *type = REG_SZ;
2353 *needed = 2*(strlen(string)+1);
2354 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2355 return WERR_NOMEM;
2356 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2357 for (i=0; i<strlen(string); i++) {
2358 (*data)[2*i]=string[i];
2359 (*data)[2*i+1]='\0';
2361 return WERR_OK;
2364 if (!StrCaseCmp(value, "DsPresent")) {
2365 *type = REG_DWORD;
2366 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2367 return WERR_NOMEM;
2369 /* only show the publish check box if we are a
2370 memeber of a AD domain */
2372 if ( lp_security() == SEC_ADS )
2373 SIVAL(*data, 0, 0x01);
2374 else
2375 SIVAL(*data, 0, 0x00);
2377 *needed = 0x4;
2378 return WERR_OK;
2381 if (!StrCaseCmp(value, "DNSMachineName")) {
2382 pstring hostname;
2384 if (!get_mydnsfullname(hostname))
2385 return WERR_BADFILE;
2386 *type = REG_SZ;
2387 *needed = 2*(strlen(hostname)+1);
2388 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2389 return WERR_NOMEM;
2390 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2391 for (i=0; i<strlen(hostname); i++) {
2392 (*data)[2*i]=hostname[i];
2393 (*data)[2*i+1]='\0';
2395 return WERR_OK;
2399 return WERR_BADFILE;
2402 /********************************************************************
2403 * spoolss_getprinterdata
2404 ********************************************************************/
2406 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2408 POLICY_HND *handle = &q_u->handle;
2409 UNISTR2 *valuename = &q_u->valuename;
2410 uint32 in_size = q_u->size;
2411 uint32 *type = &r_u->type;
2412 uint32 *out_size = &r_u->size;
2413 uint8 **data = &r_u->data;
2414 uint32 *needed = &r_u->needed;
2415 WERROR status;
2416 fstring value;
2417 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2418 NT_PRINTER_INFO_LEVEL *printer = NULL;
2419 int snum = 0;
2422 * Reminder: when it's a string, the length is in BYTES
2423 * even if UNICODE is negociated.
2425 * JFM, 4/19/1999
2428 *out_size = in_size;
2430 /* in case of problem, return some default values */
2432 *needed = 0;
2433 *type = 0;
2435 DEBUG(4,("_spoolss_getprinterdata\n"));
2437 if ( !Printer ) {
2438 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2439 status = WERR_BADFID;
2440 goto done;
2443 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2445 if ( Printer->printer_type == SPLHND_SERVER )
2446 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2447 else
2449 if ( !get_printer_snum(p,handle, &snum) ) {
2450 status = WERR_BADFID;
2451 goto done;
2454 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2455 if ( !W_ERROR_IS_OK(status) )
2456 goto done;
2458 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2460 if ( strequal(value, "ChangeId") ) {
2461 *type = REG_DWORD;
2462 *needed = sizeof(uint32);
2463 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2464 status = WERR_NOMEM;
2465 goto done;
2467 SIVAL( *data, 0, printer->info_2->changeid );
2468 status = WERR_OK;
2470 else
2471 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2474 if (*needed > *out_size)
2475 status = WERR_MORE_DATA;
2477 done:
2478 if ( !W_ERROR_IS_OK(status) )
2480 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2482 /* reply this param doesn't exist */
2484 if ( *out_size ) {
2485 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2486 if ( printer )
2487 free_a_printer( &printer, 2 );
2488 return WERR_NOMEM;
2491 else {
2492 *data = NULL;
2496 /* cleanup & exit */
2498 if ( printer )
2499 free_a_printer( &printer, 2 );
2501 return status;
2504 /*********************************************************
2505 Connect to the client machine.
2506 **********************************************************/
2508 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2509 struct in_addr *client_ip, const char *remote_machine)
2511 NTSTATUS ret;
2512 struct cli_state *the_cli;
2513 struct in_addr rm_addr;
2515 if ( is_zero_ip(*client_ip) ) {
2516 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2517 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2518 return False;
2521 if ( ismyip( rm_addr )) {
2522 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2523 return False;
2525 } else {
2526 rm_addr.s_addr = client_ip->s_addr;
2527 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2528 inet_ntoa(*client_ip) ));
2531 /* setup the connection */
2533 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2534 &rm_addr, 0, "IPC$", "IPC",
2535 "", /* username */
2536 "", /* domain */
2537 "", /* password */
2538 0, lp_client_signing(), NULL );
2540 if ( !NT_STATUS_IS_OK( ret ) ) {
2541 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2542 remote_machine ));
2543 return False;
2546 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2547 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2548 cli_shutdown(the_cli);
2549 return False;
2553 * Ok - we have an anonymous connection to the IPC$ share.
2554 * Now start the NT Domain stuff :-).
2557 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2558 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2559 remote_machine, nt_errstr(ret)));
2560 cli_shutdown(the_cli);
2561 return False;
2564 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2566 (*pp_pipe)->cli = the_cli;
2568 return True;
2571 /***************************************************************************
2572 Connect to the client.
2573 ****************************************************************************/
2575 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2576 uint32 localprinter, uint32 type,
2577 POLICY_HND *handle, struct in_addr *client_ip)
2579 WERROR result;
2582 * If it's the first connection, contact the client
2583 * and connect to the IPC$ share anonymously
2585 if (smb_connections==0) {
2586 fstring unix_printer;
2588 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2590 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
2591 return False;
2593 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2594 /* Tell the connections db we're now interested in printer
2595 * notify messages. */
2596 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2600 * Tell the specific printing tdb we want messages for this printer
2601 * by registering our PID.
2604 if (!print_notify_register_pid(snum))
2605 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2607 smb_connections++;
2609 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2610 type, handle);
2612 if (!W_ERROR_IS_OK(result))
2613 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2614 dos_errstr(result)));
2616 return (W_ERROR_IS_OK(result));
2619 /********************************************************************
2620 * _spoolss_rffpcnex
2621 * ReplyFindFirstPrinterChangeNotifyEx
2623 * before replying OK: status=0 a rpc call is made to the workstation
2624 * asking ReplyOpenPrinter
2626 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2627 * called from api_spoolss_rffpcnex
2628 ********************************************************************/
2630 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2632 POLICY_HND *handle = &q_u->handle;
2633 uint32 flags = q_u->flags;
2634 uint32 options = q_u->options;
2635 UNISTR2 *localmachine = &q_u->localmachine;
2636 uint32 printerlocal = q_u->printerlocal;
2637 int snum = -1;
2638 SPOOL_NOTIFY_OPTION *option = q_u->option;
2639 struct in_addr client_ip;
2641 /* store the notify value in the printer struct */
2643 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2645 if (!Printer) {
2646 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2647 return WERR_BADFID;
2650 Printer->notify.flags=flags;
2651 Printer->notify.options=options;
2652 Printer->notify.printerlocal=printerlocal;
2654 if (Printer->notify.option)
2655 free_spool_notify_option(&Printer->notify.option);
2657 Printer->notify.option=dup_spool_notify_option(option);
2659 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2660 sizeof(Printer->notify.localmachine)-1);
2662 /* Connect to the client machine and send a ReplyOpenPrinter */
2664 if ( Printer->printer_type == SPLHND_SERVER)
2665 snum = -1;
2666 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2667 !get_printer_snum(p, handle, &snum) )
2668 return WERR_BADFID;
2670 client_ip.s_addr = inet_addr(p->conn->client_address);
2672 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2673 Printer->notify.printerlocal, 1,
2674 &Printer->notify.client_hnd, &client_ip))
2675 return WERR_SERVER_UNAVAILABLE;
2677 Printer->notify.client_connected=True;
2679 return WERR_OK;
2682 /*******************************************************************
2683 * fill a notify_info_data with the servername
2684 ********************************************************************/
2686 void spoolss_notify_server_name(int snum,
2687 SPOOL_NOTIFY_INFO_DATA *data,
2688 print_queue_struct *queue,
2689 NT_PRINTER_INFO_LEVEL *printer,
2690 TALLOC_CTX *mem_ctx)
2692 pstring temp;
2693 uint32 len;
2695 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2697 data->notify_data.data.length = len;
2698 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2700 if (!data->notify_data.data.string) {
2701 data->notify_data.data.length = 0;
2702 return;
2705 memcpy(data->notify_data.data.string, temp, len);
2708 /*******************************************************************
2709 * fill a notify_info_data with the printername (not including the servername).
2710 ********************************************************************/
2712 void spoolss_notify_printer_name(int snum,
2713 SPOOL_NOTIFY_INFO_DATA *data,
2714 print_queue_struct *queue,
2715 NT_PRINTER_INFO_LEVEL *printer,
2716 TALLOC_CTX *mem_ctx)
2718 pstring temp;
2719 uint32 len;
2721 /* the notify name should not contain the \\server\ part */
2722 char *p = strrchr(printer->info_2->printername, '\\');
2724 if (!p) {
2725 p = printer->info_2->printername;
2726 } else {
2727 p++;
2730 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2732 data->notify_data.data.length = len;
2733 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2735 if (!data->notify_data.data.string) {
2736 data->notify_data.data.length = 0;
2737 return;
2740 memcpy(data->notify_data.data.string, temp, len);
2743 /*******************************************************************
2744 * fill a notify_info_data with the servicename
2745 ********************************************************************/
2747 void spoolss_notify_share_name(int snum,
2748 SPOOL_NOTIFY_INFO_DATA *data,
2749 print_queue_struct *queue,
2750 NT_PRINTER_INFO_LEVEL *printer,
2751 TALLOC_CTX *mem_ctx)
2753 pstring temp;
2754 uint32 len;
2756 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2758 data->notify_data.data.length = len;
2759 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2761 if (!data->notify_data.data.string) {
2762 data->notify_data.data.length = 0;
2763 return;
2766 memcpy(data->notify_data.data.string, temp, len);
2769 /*******************************************************************
2770 * fill a notify_info_data with the port name
2771 ********************************************************************/
2773 void spoolss_notify_port_name(int snum,
2774 SPOOL_NOTIFY_INFO_DATA *data,
2775 print_queue_struct *queue,
2776 NT_PRINTER_INFO_LEVEL *printer,
2777 TALLOC_CTX *mem_ctx)
2779 pstring temp;
2780 uint32 len;
2782 /* even if it's strange, that's consistant in all the code */
2784 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2786 data->notify_data.data.length = len;
2787 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2789 if (!data->notify_data.data.string) {
2790 data->notify_data.data.length = 0;
2791 return;
2794 memcpy(data->notify_data.data.string, temp, len);
2797 /*******************************************************************
2798 * fill a notify_info_data with the printername
2799 * but it doesn't exist, have to see what to do
2800 ********************************************************************/
2802 void spoolss_notify_driver_name(int snum,
2803 SPOOL_NOTIFY_INFO_DATA *data,
2804 print_queue_struct *queue,
2805 NT_PRINTER_INFO_LEVEL *printer,
2806 TALLOC_CTX *mem_ctx)
2808 pstring temp;
2809 uint32 len;
2811 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2813 data->notify_data.data.length = 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);
2824 /*******************************************************************
2825 * fill a notify_info_data with the comment
2826 ********************************************************************/
2828 void spoolss_notify_comment(int snum,
2829 SPOOL_NOTIFY_INFO_DATA *data,
2830 print_queue_struct *queue,
2831 NT_PRINTER_INFO_LEVEL *printer,
2832 TALLOC_CTX *mem_ctx)
2834 pstring temp;
2835 uint32 len;
2837 if (*printer->info_2->comment == '\0')
2838 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2839 else
2840 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2842 data->notify_data.data.length = len;
2843 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2845 if (!data->notify_data.data.string) {
2846 data->notify_data.data.length = 0;
2847 return;
2850 memcpy(data->notify_data.data.string, temp, len);
2853 /*******************************************************************
2854 * fill a notify_info_data with the comment
2855 * location = "Room 1, floor 2, building 3"
2856 ********************************************************************/
2858 void spoolss_notify_location(int snum,
2859 SPOOL_NOTIFY_INFO_DATA *data,
2860 print_queue_struct *queue,
2861 NT_PRINTER_INFO_LEVEL *printer,
2862 TALLOC_CTX *mem_ctx)
2864 pstring temp;
2865 uint32 len;
2867 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2869 data->notify_data.data.length = len;
2870 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2872 if (!data->notify_data.data.string) {
2873 data->notify_data.data.length = 0;
2874 return;
2877 memcpy(data->notify_data.data.string, temp, len);
2880 /*******************************************************************
2881 * fill a notify_info_data with the device mode
2882 * jfm:xxxx don't to it for know but that's a real problem !!!
2883 ********************************************************************/
2885 static void spoolss_notify_devmode(int snum,
2886 SPOOL_NOTIFY_INFO_DATA *data,
2887 print_queue_struct *queue,
2888 NT_PRINTER_INFO_LEVEL *printer,
2889 TALLOC_CTX *mem_ctx)
2893 /*******************************************************************
2894 * fill a notify_info_data with the separator file name
2895 ********************************************************************/
2897 void spoolss_notify_sepfile(int snum,
2898 SPOOL_NOTIFY_INFO_DATA *data,
2899 print_queue_struct *queue,
2900 NT_PRINTER_INFO_LEVEL *printer,
2901 TALLOC_CTX *mem_ctx)
2903 pstring temp;
2904 uint32 len;
2906 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2908 data->notify_data.data.length = 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);
2919 /*******************************************************************
2920 * fill a notify_info_data with the print processor
2921 * jfm:xxxx return always winprint to indicate we don't do anything to it
2922 ********************************************************************/
2924 void spoolss_notify_print_processor(int snum,
2925 SPOOL_NOTIFY_INFO_DATA *data,
2926 print_queue_struct *queue,
2927 NT_PRINTER_INFO_LEVEL *printer,
2928 TALLOC_CTX *mem_ctx)
2930 pstring temp;
2931 uint32 len;
2933 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2935 data->notify_data.data.length = len;
2936 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2938 if (!data->notify_data.data.string) {
2939 data->notify_data.data.length = 0;
2940 return;
2943 memcpy(data->notify_data.data.string, temp, len);
2946 /*******************************************************************
2947 * fill a notify_info_data with the print processor options
2948 * jfm:xxxx send an empty string
2949 ********************************************************************/
2951 void spoolss_notify_parameters(int snum,
2952 SPOOL_NOTIFY_INFO_DATA *data,
2953 print_queue_struct *queue,
2954 NT_PRINTER_INFO_LEVEL *printer,
2955 TALLOC_CTX *mem_ctx)
2957 pstring temp;
2958 uint32 len;
2960 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2962 data->notify_data.data.length = len;
2963 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2965 if (!data->notify_data.data.string) {
2966 data->notify_data.data.length = 0;
2967 return;
2970 memcpy(data->notify_data.data.string, temp, len);
2973 /*******************************************************************
2974 * fill a notify_info_data with the data type
2975 * jfm:xxxx always send RAW as data type
2976 ********************************************************************/
2978 void spoolss_notify_datatype(int snum,
2979 SPOOL_NOTIFY_INFO_DATA *data,
2980 print_queue_struct *queue,
2981 NT_PRINTER_INFO_LEVEL *printer,
2982 TALLOC_CTX *mem_ctx)
2984 pstring temp;
2985 uint32 len;
2987 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2989 data->notify_data.data.length = len;
2990 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2992 if (!data->notify_data.data.string) {
2993 data->notify_data.data.length = 0;
2994 return;
2997 memcpy(data->notify_data.data.string, temp, len);
3000 /*******************************************************************
3001 * fill a notify_info_data with the security descriptor
3002 * jfm:xxxx send an null pointer to say no security desc
3003 * have to implement security before !
3004 ********************************************************************/
3006 static void spoolss_notify_security_desc(int snum,
3007 SPOOL_NOTIFY_INFO_DATA *data,
3008 print_queue_struct *queue,
3009 NT_PRINTER_INFO_LEVEL *printer,
3010 TALLOC_CTX *mem_ctx)
3012 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3013 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3016 /*******************************************************************
3017 * fill a notify_info_data with the attributes
3018 * jfm:xxxx a samba printer is always shared
3019 ********************************************************************/
3021 void spoolss_notify_attributes(int snum,
3022 SPOOL_NOTIFY_INFO_DATA *data,
3023 print_queue_struct *queue,
3024 NT_PRINTER_INFO_LEVEL *printer,
3025 TALLOC_CTX *mem_ctx)
3027 data->notify_data.value[0] = printer->info_2->attributes;
3028 data->notify_data.value[1] = 0;
3031 /*******************************************************************
3032 * fill a notify_info_data with the priority
3033 ********************************************************************/
3035 static void spoolss_notify_priority(int snum,
3036 SPOOL_NOTIFY_INFO_DATA *data,
3037 print_queue_struct *queue,
3038 NT_PRINTER_INFO_LEVEL *printer,
3039 TALLOC_CTX *mem_ctx)
3041 data->notify_data.value[0] = printer->info_2->priority;
3042 data->notify_data.value[1] = 0;
3045 /*******************************************************************
3046 * fill a notify_info_data with the default priority
3047 ********************************************************************/
3049 static void spoolss_notify_default_priority(int snum,
3050 SPOOL_NOTIFY_INFO_DATA *data,
3051 print_queue_struct *queue,
3052 NT_PRINTER_INFO_LEVEL *printer,
3053 TALLOC_CTX *mem_ctx)
3055 data->notify_data.value[0] = printer->info_2->default_priority;
3056 data->notify_data.value[1] = 0;
3059 /*******************************************************************
3060 * fill a notify_info_data with the start time
3061 ********************************************************************/
3063 static void spoolss_notify_start_time(int snum,
3064 SPOOL_NOTIFY_INFO_DATA *data,
3065 print_queue_struct *queue,
3066 NT_PRINTER_INFO_LEVEL *printer,
3067 TALLOC_CTX *mem_ctx)
3069 data->notify_data.value[0] = printer->info_2->starttime;
3070 data->notify_data.value[1] = 0;
3073 /*******************************************************************
3074 * fill a notify_info_data with the until time
3075 ********************************************************************/
3077 static void spoolss_notify_until_time(int snum,
3078 SPOOL_NOTIFY_INFO_DATA *data,
3079 print_queue_struct *queue,
3080 NT_PRINTER_INFO_LEVEL *printer,
3081 TALLOC_CTX *mem_ctx)
3083 data->notify_data.value[0] = printer->info_2->untiltime;
3084 data->notify_data.value[1] = 0;
3087 /*******************************************************************
3088 * fill a notify_info_data with the status
3089 ********************************************************************/
3091 static void spoolss_notify_status(int snum,
3092 SPOOL_NOTIFY_INFO_DATA *data,
3093 print_queue_struct *queue,
3094 NT_PRINTER_INFO_LEVEL *printer,
3095 TALLOC_CTX *mem_ctx)
3097 print_status_struct status;
3099 print_queue_length(snum, &status);
3100 data->notify_data.value[0]=(uint32) status.status;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the number of jobs queued
3106 ********************************************************************/
3108 void spoolss_notify_cjobs(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = print_queue_length(snum, NULL);
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the average ppm
3120 ********************************************************************/
3122 static void spoolss_notify_average_ppm(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 /* always respond 8 pages per minutes */
3129 /* a little hard ! */
3130 data->notify_data.value[0] = printer->info_2->averageppm;
3131 data->notify_data.value[1] = 0;
3134 /*******************************************************************
3135 * fill a notify_info_data with username
3136 ********************************************************************/
3138 static void spoolss_notify_username(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 pstring temp;
3145 uint32 len;
3147 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3149 data->notify_data.data.length = len;
3150 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3152 if (!data->notify_data.data.string) {
3153 data->notify_data.data.length = 0;
3154 return;
3157 memcpy(data->notify_data.data.string, temp, len);
3160 /*******************************************************************
3161 * fill a notify_info_data with job status
3162 ********************************************************************/
3164 static void spoolss_notify_job_status(int snum,
3165 SPOOL_NOTIFY_INFO_DATA *data,
3166 print_queue_struct *queue,
3167 NT_PRINTER_INFO_LEVEL *printer,
3168 TALLOC_CTX *mem_ctx)
3170 data->notify_data.value[0]=nt_printj_status(queue->status);
3171 data->notify_data.value[1] = 0;
3174 /*******************************************************************
3175 * fill a notify_info_data with job name
3176 ********************************************************************/
3178 static void spoolss_notify_job_name(int snum,
3179 SPOOL_NOTIFY_INFO_DATA *data,
3180 print_queue_struct *queue,
3181 NT_PRINTER_INFO_LEVEL *printer,
3182 TALLOC_CTX *mem_ctx)
3184 pstring temp;
3185 uint32 len;
3187 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3189 data->notify_data.data.length = len;
3190 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3192 if (!data->notify_data.data.string) {
3193 data->notify_data.data.length = 0;
3194 return;
3197 memcpy(data->notify_data.data.string, temp, len);
3200 /*******************************************************************
3201 * fill a notify_info_data with job status
3202 ********************************************************************/
3204 static void spoolss_notify_job_status_string(int snum,
3205 SPOOL_NOTIFY_INFO_DATA *data,
3206 print_queue_struct *queue,
3207 NT_PRINTER_INFO_LEVEL *printer,
3208 TALLOC_CTX *mem_ctx)
3211 * Now we're returning job status codes we just return a "" here. JRA.
3214 const char *p = "";
3215 pstring temp;
3216 uint32 len;
3218 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3219 p = "unknown";
3221 switch (queue->status) {
3222 case LPQ_QUEUED:
3223 p = "Queued";
3224 break;
3225 case LPQ_PAUSED:
3226 p = ""; /* NT provides the paused string */
3227 break;
3228 case LPQ_SPOOLING:
3229 p = "Spooling";
3230 break;
3231 case LPQ_PRINTING:
3232 p = "Printing";
3233 break;
3235 #endif /* NO LONGER NEEDED. */
3237 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3239 data->notify_data.data.length = len;
3240 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3242 if (!data->notify_data.data.string) {
3243 data->notify_data.data.length = 0;
3244 return;
3247 memcpy(data->notify_data.data.string, temp, len);
3250 /*******************************************************************
3251 * fill a notify_info_data with job time
3252 ********************************************************************/
3254 static void spoolss_notify_job_time(int snum,
3255 SPOOL_NOTIFY_INFO_DATA *data,
3256 print_queue_struct *queue,
3257 NT_PRINTER_INFO_LEVEL *printer,
3258 TALLOC_CTX *mem_ctx)
3260 data->notify_data.value[0]=0x0;
3261 data->notify_data.value[1]=0;
3264 /*******************************************************************
3265 * fill a notify_info_data with job size
3266 ********************************************************************/
3268 static void spoolss_notify_job_size(int snum,
3269 SPOOL_NOTIFY_INFO_DATA *data,
3270 print_queue_struct *queue,
3271 NT_PRINTER_INFO_LEVEL *printer,
3272 TALLOC_CTX *mem_ctx)
3274 data->notify_data.value[0]=queue->size;
3275 data->notify_data.value[1]=0;
3278 /*******************************************************************
3279 * fill a notify_info_data with page info
3280 ********************************************************************/
3281 static void spoolss_notify_total_pages(int snum,
3282 SPOOL_NOTIFY_INFO_DATA *data,
3283 print_queue_struct *queue,
3284 NT_PRINTER_INFO_LEVEL *printer,
3285 TALLOC_CTX *mem_ctx)
3287 data->notify_data.value[0]=queue->page_count;
3288 data->notify_data.value[1]=0;
3291 /*******************************************************************
3292 * fill a notify_info_data with pages printed info.
3293 ********************************************************************/
3294 static void spoolss_notify_pages_printed(int snum,
3295 SPOOL_NOTIFY_INFO_DATA *data,
3296 print_queue_struct *queue,
3297 NT_PRINTER_INFO_LEVEL *printer,
3298 TALLOC_CTX *mem_ctx)
3300 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3301 data->notify_data.value[1]=0;
3304 /*******************************************************************
3305 Fill a notify_info_data with job position.
3306 ********************************************************************/
3308 static void spoolss_notify_job_position(int snum,
3309 SPOOL_NOTIFY_INFO_DATA *data,
3310 print_queue_struct *queue,
3311 NT_PRINTER_INFO_LEVEL *printer,
3312 TALLOC_CTX *mem_ctx)
3314 data->notify_data.value[0]=queue->job;
3315 data->notify_data.value[1]=0;
3318 /*******************************************************************
3319 Fill a notify_info_data with submitted time.
3320 ********************************************************************/
3322 static void spoolss_notify_submitted_time(int snum,
3323 SPOOL_NOTIFY_INFO_DATA *data,
3324 print_queue_struct *queue,
3325 NT_PRINTER_INFO_LEVEL *printer,
3326 TALLOC_CTX *mem_ctx)
3328 struct tm *t;
3329 uint32 len;
3330 SYSTEMTIME st;
3331 char *p;
3333 t=gmtime(&queue->time);
3335 len = sizeof(SYSTEMTIME);
3337 data->notify_data.data.length = len;
3338 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3340 if (!data->notify_data.data.string) {
3341 data->notify_data.data.length = 0;
3342 return;
3345 make_systemtime(&st, t);
3348 * Systemtime must be linearized as a set of UINT16's.
3349 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3352 p = (char *)data->notify_data.data.string;
3353 SSVAL(p, 0, st.year);
3354 SSVAL(p, 2, st.month);
3355 SSVAL(p, 4, st.dayofweek);
3356 SSVAL(p, 6, st.day);
3357 SSVAL(p, 8, st.hour);
3358 SSVAL(p, 10, st.minute);
3359 SSVAL(p, 12, st.second);
3360 SSVAL(p, 14, st.milliseconds);
3363 struct s_notify_info_data_table
3365 uint16 type;
3366 uint16 field;
3367 const char *name;
3368 uint32 size;
3369 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3370 print_queue_struct *queue,
3371 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3374 /* A table describing the various print notification constants and
3375 whether the notification data is a pointer to a variable sized
3376 buffer, a one value uint32 or a two value uint32. */
3378 static const struct s_notify_info_data_table notify_info_data_table[] =
3380 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3381 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3382 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3406 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3407 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3408 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3409 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3429 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3432 /*******************************************************************
3433 Return the size of info_data structure.
3434 ********************************************************************/
3436 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3438 int i=0;
3440 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3441 if ( (notify_info_data_table[i].type == type)
3442 && (notify_info_data_table[i].field == field) ) {
3443 switch(notify_info_data_table[i].size) {
3444 case NOTIFY_ONE_VALUE:
3445 case NOTIFY_TWO_VALUE:
3446 return 1;
3447 case NOTIFY_STRING:
3448 return 2;
3450 /* The only pointer notify data I have seen on
3451 the wire is the submitted time and this has
3452 the notify size set to 4. -tpot */
3454 case NOTIFY_POINTER:
3455 return 4;
3457 case NOTIFY_SECDESC:
3458 return 5;
3463 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3465 return 0;
3468 /*******************************************************************
3469 Return the type of notify_info_data.
3470 ********************************************************************/
3472 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3474 uint32 i=0;
3476 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3477 if (notify_info_data_table[i].type == type &&
3478 notify_info_data_table[i].field == field)
3479 return notify_info_data_table[i].size;
3482 return 0;
3485 /****************************************************************************
3486 ****************************************************************************/
3488 static BOOL search_notify(uint16 type, uint16 field, int *value)
3490 int i;
3492 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3493 if (notify_info_data_table[i].type == type &&
3494 notify_info_data_table[i].field == field &&
3495 notify_info_data_table[i].fn != NULL) {
3496 *value = i;
3497 return True;
3501 return False;
3504 /****************************************************************************
3505 ****************************************************************************/
3507 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3509 info_data->type = type;
3510 info_data->field = field;
3511 info_data->reserved = 0;
3513 info_data->size = size_of_notify_info_data(type, field);
3514 info_data->enc_type = type_of_notify_info_data(type, field);
3516 info_data->id = id;
3519 /*******************************************************************
3521 * fill a notify_info struct with info asked
3523 ********************************************************************/
3525 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3526 snum, SPOOL_NOTIFY_OPTION_TYPE
3527 *option_type, uint32 id,
3528 TALLOC_CTX *mem_ctx)
3530 int field_num,j;
3531 uint16 type;
3532 uint16 field;
3534 SPOOL_NOTIFY_INFO_DATA *current_data;
3535 NT_PRINTER_INFO_LEVEL *printer = NULL;
3536 print_queue_struct *queue=NULL;
3538 type=option_type->type;
3540 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3541 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3542 option_type->count, lp_servicename(snum)));
3544 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3545 return False;
3547 for(field_num=0; field_num<option_type->count; field_num++) {
3548 field = option_type->fields[field_num];
3550 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3552 if (!search_notify(type, field, &j) )
3553 continue;
3555 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3556 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3557 free_a_printer(&printer, 2);
3558 return False;
3561 current_data = &info->data[info->count];
3563 construct_info_data(current_data, type, field, id);
3565 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3566 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3568 notify_info_data_table[j].fn(snum, current_data, queue,
3569 printer, mem_ctx);
3571 info->count++;
3574 free_a_printer(&printer, 2);
3575 return True;
3578 /*******************************************************************
3580 * fill a notify_info struct with info asked
3582 ********************************************************************/
3584 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3585 SPOOL_NOTIFY_INFO *info,
3586 NT_PRINTER_INFO_LEVEL *printer,
3587 int snum, SPOOL_NOTIFY_OPTION_TYPE
3588 *option_type, uint32 id,
3589 TALLOC_CTX *mem_ctx)
3591 int field_num,j;
3592 uint16 type;
3593 uint16 field;
3595 SPOOL_NOTIFY_INFO_DATA *current_data;
3597 DEBUG(4,("construct_notify_jobs_info\n"));
3599 type = option_type->type;
3601 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3602 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3603 option_type->count));
3605 for(field_num=0; field_num<option_type->count; field_num++) {
3606 field = option_type->fields[field_num];
3608 if (!search_notify(type, field, &j) )
3609 continue;
3611 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3612 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3613 return False;
3616 current_data=&(info->data[info->count]);
3618 construct_info_data(current_data, type, field, id);
3619 notify_info_data_table[j].fn(snum, current_data, queue,
3620 printer, mem_ctx);
3621 info->count++;
3624 return True;
3628 * JFM: The enumeration is not that simple, it's even non obvious.
3630 * let's take an example: I want to monitor the PRINTER SERVER for
3631 * the printer's name and the number of jobs currently queued.
3632 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3633 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3635 * I have 3 printers on the back of my server.
3637 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3638 * structures.
3639 * Number Data Id
3640 * 1 printer 1 name 1
3641 * 2 printer 1 cjob 1
3642 * 3 printer 2 name 2
3643 * 4 printer 2 cjob 2
3644 * 5 printer 3 name 3
3645 * 6 printer 3 name 3
3647 * that's the print server case, the printer case is even worse.
3650 /*******************************************************************
3652 * enumerate all printers on the printserver
3653 * fill a notify_info struct with info asked
3655 ********************************************************************/
3657 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3658 SPOOL_NOTIFY_INFO *info,
3659 TALLOC_CTX *mem_ctx)
3661 int snum;
3662 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3663 int n_services=lp_numservices();
3664 int i;
3665 SPOOL_NOTIFY_OPTION *option;
3666 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3668 DEBUG(4,("printserver_notify_info\n"));
3670 if (!Printer)
3671 return WERR_BADFID;
3673 option=Printer->notify.option;
3674 info->version=2;
3675 info->data=NULL;
3676 info->count=0;
3678 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3679 sending a ffpcn() request first */
3681 if ( !option )
3682 return WERR_BADFID;
3684 for (i=0; i<option->count; i++) {
3685 option_type=&(option->ctr.type[i]);
3687 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3688 continue;
3690 for (snum=0; snum<n_services; snum++)
3692 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3693 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3697 #if 0
3699 * Debugging information, don't delete.
3702 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3703 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3704 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3706 for (i=0; i<info->count; i++) {
3707 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3708 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3709 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3711 #endif
3713 return WERR_OK;
3716 /*******************************************************************
3718 * fill a notify_info struct with info asked
3720 ********************************************************************/
3722 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3723 TALLOC_CTX *mem_ctx)
3725 int snum;
3726 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3727 int i;
3728 uint32 id;
3729 SPOOL_NOTIFY_OPTION *option;
3730 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3731 int count,j;
3732 print_queue_struct *queue=NULL;
3733 print_status_struct status;
3735 DEBUG(4,("printer_notify_info\n"));
3737 if (!Printer)
3738 return WERR_BADFID;
3740 option=Printer->notify.option;
3741 id = 0x0;
3742 info->version=2;
3743 info->data=NULL;
3744 info->count=0;
3746 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3747 sending a ffpcn() request first */
3749 if ( !option )
3750 return WERR_BADFID;
3752 get_printer_snum(p, hnd, &snum);
3754 for (i=0; i<option->count; i++) {
3755 option_type=&option->ctr.type[i];
3757 switch ( option_type->type ) {
3758 case PRINTER_NOTIFY_TYPE:
3759 if(construct_notify_printer_info(Printer, info, snum,
3760 option_type, id,
3761 mem_ctx))
3762 id--;
3763 break;
3765 case JOB_NOTIFY_TYPE: {
3766 NT_PRINTER_INFO_LEVEL *printer = NULL;
3768 count = print_queue_status(snum, &queue, &status);
3770 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3771 goto done;
3773 for (j=0; j<count; j++) {
3774 construct_notify_jobs_info(&queue[j], info,
3775 printer, snum,
3776 option_type,
3777 queue[j].job,
3778 mem_ctx);
3781 free_a_printer(&printer, 2);
3783 done:
3784 SAFE_FREE(queue);
3785 break;
3791 * Debugging information, don't delete.
3794 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3795 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3796 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3798 for (i=0; i<info->count; i++) {
3799 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3800 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3801 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3804 return WERR_OK;
3807 /********************************************************************
3808 * spoolss_rfnpcnex
3809 ********************************************************************/
3811 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3813 POLICY_HND *handle = &q_u->handle;
3814 SPOOL_NOTIFY_INFO *info = &r_u->info;
3816 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3817 WERROR result = WERR_BADFID;
3819 /* we always have a NOTIFY_INFO struct */
3820 r_u->info_ptr=0x1;
3822 if (!Printer) {
3823 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3824 OUR_HANDLE(handle)));
3825 goto done;
3828 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3831 * We are now using the change value, and
3832 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3833 * I don't have a global notification system, I'm sending back all the
3834 * informations even when _NOTHING_ has changed.
3837 /* We need to keep track of the change value to send back in
3838 RRPCN replies otherwise our updates are ignored. */
3840 Printer->notify.fnpcn = True;
3842 if (Printer->notify.client_connected) {
3843 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3844 Printer->notify.change = q_u->change;
3847 /* just ignore the SPOOL_NOTIFY_OPTION */
3849 switch (Printer->printer_type) {
3850 case SPLHND_SERVER:
3851 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3852 break;
3854 case SPLHND_PRINTER:
3855 result = printer_notify_info(p, handle, info, p->mem_ctx);
3856 break;
3859 Printer->notify.fnpcn = False;
3861 done:
3862 return result;
3865 /********************************************************************
3866 * construct_printer_info_0
3867 * fill a printer_info_0 struct
3868 ********************************************************************/
3870 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3872 pstring chaine;
3873 int count;
3874 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3875 counter_printer_0 *session_counter;
3876 uint32 global_counter;
3877 struct tm *t;
3878 time_t setuptime;
3879 print_status_struct status;
3881 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3882 return False;
3884 count = print_queue_length(snum, &status);
3886 /* check if we already have a counter for this printer */
3887 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3888 if (session_counter->snum == snum)
3889 break;
3892 /* it's the first time, add it to the list */
3893 if (session_counter==NULL) {
3894 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3895 free_a_printer(&ntprinter, 2);
3896 return False;
3898 ZERO_STRUCTP(session_counter);
3899 session_counter->snum=snum;
3900 session_counter->counter=0;
3901 DLIST_ADD(counter_list, session_counter);
3904 /* increment it */
3905 session_counter->counter++;
3907 /* JFM:
3908 * the global_counter should be stored in a TDB as it's common to all the clients
3909 * and should be zeroed on samba startup
3911 global_counter=session_counter->counter;
3913 pstrcpy(chaine,ntprinter->info_2->printername);
3915 init_unistr(&printer->printername, chaine);
3917 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3918 init_unistr(&printer->servername, chaine);
3920 printer->cjobs = count;
3921 printer->total_jobs = 0;
3922 printer->total_bytes = 0;
3924 setuptime = (time_t)ntprinter->info_2->setuptime;
3925 t=gmtime(&setuptime);
3927 printer->year = t->tm_year+1900;
3928 printer->month = t->tm_mon+1;
3929 printer->dayofweek = t->tm_wday;
3930 printer->day = t->tm_mday;
3931 printer->hour = t->tm_hour;
3932 printer->minute = t->tm_min;
3933 printer->second = t->tm_sec;
3934 printer->milliseconds = 0;
3936 printer->global_counter = global_counter;
3937 printer->total_pages = 0;
3939 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3940 printer->major_version = 0x0005; /* NT 5 */
3941 printer->build_version = 0x0893; /* build 2195 */
3943 printer->unknown7 = 0x1;
3944 printer->unknown8 = 0x0;
3945 printer->unknown9 = 0x0;
3946 printer->session_counter = session_counter->counter;
3947 printer->unknown11 = 0x0;
3948 printer->printer_errors = 0x0; /* number of print failure */
3949 printer->unknown13 = 0x0;
3950 printer->unknown14 = 0x1;
3951 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3952 printer->unknown16 = 0x0;
3953 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3954 printer->unknown18 = 0x0;
3955 printer->status = nt_printq_status(status.status);
3956 printer->unknown20 = 0x0;
3957 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3958 printer->unknown22 = 0x0;
3959 printer->unknown23 = 0x6; /* 6 ???*/
3960 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3961 printer->unknown25 = 0;
3962 printer->unknown26 = 0;
3963 printer->unknown27 = 0;
3964 printer->unknown28 = 0;
3965 printer->unknown29 = 0;
3967 free_a_printer(&ntprinter,2);
3968 return (True);
3971 /********************************************************************
3972 * construct_printer_info_1
3973 * fill a printer_info_1 struct
3974 ********************************************************************/
3975 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3977 pstring chaine;
3978 pstring chaine2;
3979 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3981 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3982 return False;
3984 printer->flags=flags;
3986 if (*ntprinter->info_2->comment == '\0') {
3987 init_unistr(&printer->comment, lp_comment(snum));
3988 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3989 ntprinter->info_2->drivername, lp_comment(snum));
3991 else {
3992 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3993 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3994 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3997 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3999 init_unistr(&printer->description, chaine);
4000 init_unistr(&printer->name, chaine2);
4002 free_a_printer(&ntprinter,2);
4004 return True;
4007 /****************************************************************************
4008 Free a DEVMODE struct.
4009 ****************************************************************************/
4011 static void free_dev_mode(DEVICEMODE *dev)
4013 if (dev == NULL)
4014 return;
4016 SAFE_FREE(dev->dev_private);
4017 SAFE_FREE(dev);
4021 /****************************************************************************
4022 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4023 should be valid upon entry
4024 ****************************************************************************/
4026 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4028 if ( !devmode || !ntdevmode )
4029 return False;
4031 init_unistr(&devmode->devicename, ntdevmode->devicename);
4033 init_unistr(&devmode->formname, ntdevmode->formname);
4035 devmode->specversion = ntdevmode->specversion;
4036 devmode->driverversion = ntdevmode->driverversion;
4037 devmode->size = ntdevmode->size;
4038 devmode->driverextra = ntdevmode->driverextra;
4039 devmode->fields = ntdevmode->fields;
4041 devmode->orientation = ntdevmode->orientation;
4042 devmode->papersize = ntdevmode->papersize;
4043 devmode->paperlength = ntdevmode->paperlength;
4044 devmode->paperwidth = ntdevmode->paperwidth;
4045 devmode->scale = ntdevmode->scale;
4046 devmode->copies = ntdevmode->copies;
4047 devmode->defaultsource = ntdevmode->defaultsource;
4048 devmode->printquality = ntdevmode->printquality;
4049 devmode->color = ntdevmode->color;
4050 devmode->duplex = ntdevmode->duplex;
4051 devmode->yresolution = ntdevmode->yresolution;
4052 devmode->ttoption = ntdevmode->ttoption;
4053 devmode->collate = ntdevmode->collate;
4054 devmode->icmmethod = ntdevmode->icmmethod;
4055 devmode->icmintent = ntdevmode->icmintent;
4056 devmode->mediatype = ntdevmode->mediatype;
4057 devmode->dithertype = ntdevmode->dithertype;
4059 if (ntdevmode->nt_dev_private != NULL) {
4060 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4061 return False;
4064 return True;
4067 /****************************************************************************
4068 Create a DEVMODE struct. Returns malloced memory.
4069 ****************************************************************************/
4071 DEVICEMODE *construct_dev_mode(const char *servicename)
4073 NT_PRINTER_INFO_LEVEL *printer = NULL;
4074 DEVICEMODE *devmode = NULL;
4076 DEBUG(7,("construct_dev_mode\n"));
4078 DEBUGADD(8,("getting printer characteristics\n"));
4080 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4081 return NULL;
4083 if ( !printer->info_2->devmode ) {
4084 DEBUG(5, ("BONG! There was no device mode!\n"));
4085 goto done;
4088 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4089 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4090 goto done;
4093 ZERO_STRUCTP(devmode);
4095 DEBUGADD(8,("loading DEVICEMODE\n"));
4097 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4098 free_dev_mode( devmode );
4099 devmode = NULL;
4102 done:
4103 free_a_printer(&printer,2);
4105 return devmode;
4108 /********************************************************************
4109 * construct_printer_info_2
4110 * fill a printer_info_2 struct
4111 ********************************************************************/
4113 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4115 int count;
4116 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4118 print_status_struct status;
4120 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4121 return False;
4123 count = print_queue_length(snum, &status);
4125 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4126 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4127 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4128 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4129 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4131 if (*ntprinter->info_2->comment == '\0')
4132 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4133 else
4134 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4136 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4137 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4138 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4139 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4140 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4142 printer->attributes = ntprinter->info_2->attributes;
4144 printer->priority = ntprinter->info_2->priority; /* priority */
4145 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4146 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4147 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4148 printer->status = nt_printq_status(status.status); /* status */
4149 printer->cjobs = count; /* jobs */
4150 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4152 if ( !(printer->devmode = construct_dev_mode(lp_const_servicename(snum))) )
4153 DEBUG(8, ("Returning NULL Devicemode!\n"));
4155 printer->secdesc = NULL;
4157 if ( ntprinter->info_2->secdesc_buf
4158 && ntprinter->info_2->secdesc_buf->len != 0 )
4160 /* don't use talloc_steal() here unless you do a deep steal of all
4161 the SEC_DESC members */
4163 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4164 ntprinter->info_2->secdesc_buf->sec );
4167 free_a_printer(&ntprinter, 2);
4169 return True;
4172 /********************************************************************
4173 * construct_printer_info_3
4174 * fill a printer_info_3 struct
4175 ********************************************************************/
4177 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4179 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4180 PRINTER_INFO_3 *printer = NULL;
4182 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4183 return False;
4185 *pp_printer = NULL;
4186 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4187 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4188 free_a_printer(&ntprinter, 2);
4189 return False;
4192 ZERO_STRUCTP(printer);
4194 /* These are the components of the SD we are returning. */
4196 printer->flags = 0x4;
4198 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4199 /* don't use talloc_steal() here unless you do a deep steal of all
4200 the SEC_DESC members */
4202 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4203 ntprinter->info_2->secdesc_buf->sec );
4206 free_a_printer(&ntprinter, 2);
4208 *pp_printer = printer;
4209 return True;
4212 /********************************************************************
4213 * construct_printer_info_4
4214 * fill a printer_info_4 struct
4215 ********************************************************************/
4217 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4219 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4221 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4222 return False;
4224 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4225 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4226 printer->attributes = ntprinter->info_2->attributes;
4228 free_a_printer(&ntprinter, 2);
4229 return True;
4232 /********************************************************************
4233 * construct_printer_info_5
4234 * fill a printer_info_5 struct
4235 ********************************************************************/
4237 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4239 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4241 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4242 return False;
4244 init_unistr(&printer->printername, ntprinter->info_2->printername);
4245 init_unistr(&printer->portname, ntprinter->info_2->portname);
4246 printer->attributes = ntprinter->info_2->attributes;
4248 /* these two are not used by NT+ according to MSDN */
4250 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4251 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4253 free_a_printer(&ntprinter, 2);
4255 return True;
4258 /********************************************************************
4259 * construct_printer_info_7
4260 * fill a printer_info_7 struct
4261 ********************************************************************/
4263 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4265 char *guid_str = NULL;
4266 struct uuid guid;
4268 if (is_printer_published(print_hnd, snum, &guid)) {
4269 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4270 strupper_m(guid_str);
4271 init_unistr(&printer->guid, guid_str);
4272 printer->action = SPOOL_DS_PUBLISH;
4273 } else {
4274 init_unistr(&printer->guid, "");
4275 printer->action = SPOOL_DS_UNPUBLISH;
4278 return True;
4281 /********************************************************************
4282 Spoolss_enumprinters.
4283 ********************************************************************/
4285 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4287 int snum;
4288 int i;
4289 int n_services=lp_numservices();
4290 PRINTER_INFO_1 *printers=NULL;
4291 PRINTER_INFO_1 current_prt;
4292 WERROR result = WERR_OK;
4294 DEBUG(4,("enum_all_printers_info_1\n"));
4296 for (snum=0; snum<n_services; snum++) {
4297 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4298 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4300 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4301 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4302 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4303 *returned=0;
4304 return WERR_NOMEM;
4306 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4308 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4309 (*returned)++;
4314 /* check the required size. */
4315 for (i=0; i<*returned; i++)
4316 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4318 if (*needed > offered) {
4319 result = WERR_INSUFFICIENT_BUFFER;
4320 goto out;
4323 if (!rpcbuf_alloc_size(buffer, *needed)) {
4324 result = WERR_NOMEM;
4325 goto out;
4328 /* fill the buffer with the structures */
4329 for (i=0; i<*returned; i++)
4330 smb_io_printer_info_1("", buffer, &printers[i], 0);
4332 out:
4333 /* clear memory */
4335 SAFE_FREE(printers);
4337 if ( !W_ERROR_IS_OK(result) )
4338 *returned = 0;
4340 return result;
4343 /********************************************************************
4344 enum_all_printers_info_1_local.
4345 *********************************************************************/
4347 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4349 DEBUG(4,("enum_all_printers_info_1_local\n"));
4351 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4354 /********************************************************************
4355 enum_all_printers_info_1_name.
4356 *********************************************************************/
4358 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4360 char *s = name;
4362 DEBUG(4,("enum_all_printers_info_1_name\n"));
4364 if ((name[0] == '\\') && (name[1] == '\\'))
4365 s = name + 2;
4367 if (is_myname_or_ipaddr(s)) {
4368 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4370 else
4371 return WERR_INVALID_NAME;
4374 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4375 /********************************************************************
4376 enum_all_printers_info_1_remote.
4377 *********************************************************************/
4379 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4381 PRINTER_INFO_1 *printer;
4382 fstring printername;
4383 fstring desc;
4384 fstring comment;
4385 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4386 WERROR result = WERR_OK;
4388 /* JFM: currently it's more a place holder than anything else.
4389 * In the spooler world there is a notion of server registration.
4390 * the print servers are registered on the PDC (in the same domain)
4392 * We should have a TDB here. The registration is done thru an
4393 * undocumented RPC call.
4396 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4397 return WERR_NOMEM;
4399 *returned=1;
4401 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4402 slprintf(desc, sizeof(desc)-1,"%s", name);
4403 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4405 init_unistr(&printer->description, desc);
4406 init_unistr(&printer->name, printername);
4407 init_unistr(&printer->comment, comment);
4408 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4410 /* check the required size. */
4411 *needed += spoolss_size_printer_info_1(printer);
4413 if (*needed > offered) {
4414 result = WERR_INSUFFICIENT_BUFFER;
4415 goto out;
4418 if (!rpcbuf_alloc_size(buffer, *needed)) {
4419 result = WERR_NOMEM;
4420 goto out;
4423 /* fill the buffer with the structures */
4424 smb_io_printer_info_1("", buffer, printer, 0);
4426 out:
4427 /* clear memory */
4428 SAFE_FREE(printer);
4430 if ( !W_ERROR_IS_OK(result) )
4431 *returned = 0;
4433 return result;
4436 #endif
4438 /********************************************************************
4439 enum_all_printers_info_1_network.
4440 *********************************************************************/
4442 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4444 char *s = name;
4446 DEBUG(4,("enum_all_printers_info_1_network\n"));
4448 /* If we respond to a enum_printers level 1 on our name with flags
4449 set to PRINTER_ENUM_REMOTE with a list of printers then these
4450 printers incorrectly appear in the APW browse list.
4451 Specifically the printers for the server appear at the workgroup
4452 level where all the other servers in the domain are
4453 listed. Windows responds to this call with a
4454 WERR_CAN_NOT_COMPLETE so we should do the same. */
4456 if (name[0] == '\\' && name[1] == '\\')
4457 s = name + 2;
4459 if (is_myname_or_ipaddr(s))
4460 return WERR_CAN_NOT_COMPLETE;
4462 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4465 /********************************************************************
4466 * api_spoolss_enumprinters
4468 * called from api_spoolss_enumprinters (see this to understand)
4469 ********************************************************************/
4471 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4473 int snum;
4474 int i;
4475 int n_services=lp_numservices();
4476 PRINTER_INFO_2 *printers=NULL;
4477 PRINTER_INFO_2 current_prt;
4478 WERROR result = WERR_OK;
4480 *returned = 0;
4482 for (snum=0; snum<n_services; snum++) {
4483 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4484 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4486 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4487 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4488 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4489 *returned = 0;
4490 return WERR_NOMEM;
4493 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4495 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4497 (*returned)++;
4502 /* check the required size. */
4503 for (i=0; i<*returned; i++)
4504 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4506 if (*needed > offered) {
4507 result = WERR_INSUFFICIENT_BUFFER;
4508 goto out;
4511 if (!rpcbuf_alloc_size(buffer, *needed)) {
4512 result = WERR_NOMEM;
4513 goto out;
4516 /* fill the buffer with the structures */
4517 for (i=0; i<*returned; i++)
4518 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4520 out:
4521 /* clear memory */
4523 for (i=0; i<*returned; i++)
4524 free_devmode(printers[i].devmode);
4526 SAFE_FREE(printers);
4528 if ( !W_ERROR_IS_OK(result) )
4529 *returned = 0;
4531 return result;
4534 /********************************************************************
4535 * handle enumeration of printers at level 1
4536 ********************************************************************/
4538 static WERROR enumprinters_level1( uint32 flags, fstring name,
4539 RPC_BUFFER *buffer, uint32 offered,
4540 uint32 *needed, uint32 *returned)
4542 /* Not all the flags are equals */
4544 if (flags & PRINTER_ENUM_LOCAL)
4545 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4547 if (flags & PRINTER_ENUM_NAME)
4548 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4550 #if 0 /* JERRY - disabled for now */
4551 if (flags & PRINTER_ENUM_REMOTE)
4552 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4553 #endif
4555 if (flags & PRINTER_ENUM_NETWORK)
4556 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4558 return WERR_OK; /* NT4sp5 does that */
4561 /********************************************************************
4562 * handle enumeration of printers at level 2
4563 ********************************************************************/
4565 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4566 RPC_BUFFER *buffer, uint32 offered,
4567 uint32 *needed, uint32 *returned)
4569 char *s = servername;
4571 if (flags & PRINTER_ENUM_LOCAL) {
4572 return enum_all_printers_info_2(buffer, offered, needed, returned);
4575 if (flags & PRINTER_ENUM_NAME) {
4576 if ((servername[0] == '\\') && (servername[1] == '\\'))
4577 s = servername + 2;
4578 if (is_myname_or_ipaddr(s))
4579 return enum_all_printers_info_2(buffer, offered, needed, returned);
4580 else
4581 return WERR_INVALID_NAME;
4584 if (flags & PRINTER_ENUM_REMOTE)
4585 return WERR_UNKNOWN_LEVEL;
4587 return WERR_OK;
4590 /********************************************************************
4591 * handle enumeration of printers at level 5
4592 ********************************************************************/
4594 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4595 RPC_BUFFER *buffer, uint32 offered,
4596 uint32 *needed, uint32 *returned)
4598 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4599 return WERR_OK;
4602 /********************************************************************
4603 * api_spoolss_enumprinters
4605 * called from api_spoolss_enumprinters (see this to understand)
4606 ********************************************************************/
4608 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4610 uint32 flags = q_u->flags;
4611 UNISTR2 *servername = &q_u->servername;
4612 uint32 level = q_u->level;
4613 RPC_BUFFER *buffer = NULL;
4614 uint32 offered = q_u->offered;
4615 uint32 *needed = &r_u->needed;
4616 uint32 *returned = &r_u->returned;
4618 fstring name;
4620 /* that's an [in out] buffer */
4622 if (!q_u->buffer && (offered!=0)) {
4623 return WERR_INVALID_PARAM;
4626 rpcbuf_move(q_u->buffer, &r_u->buffer);
4627 buffer = r_u->buffer;
4629 DEBUG(4,("_spoolss_enumprinters\n"));
4631 *needed=0;
4632 *returned=0;
4635 * Level 1:
4636 * flags==PRINTER_ENUM_NAME
4637 * if name=="" then enumerates all printers
4638 * if name!="" then enumerate the printer
4639 * flags==PRINTER_ENUM_REMOTE
4640 * name is NULL, enumerate printers
4641 * Level 2: name!="" enumerates printers, name can't be NULL
4642 * Level 3: doesn't exist
4643 * Level 4: does a local registry lookup
4644 * Level 5: same as Level 2
4647 unistr2_to_ascii(name, servername, sizeof(name)-1);
4648 strupper_m(name);
4650 switch (level) {
4651 case 1:
4652 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4653 case 2:
4654 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4655 case 5:
4656 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4657 case 3:
4658 case 4:
4659 break;
4661 return WERR_UNKNOWN_LEVEL;
4664 /****************************************************************************
4665 ****************************************************************************/
4667 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4669 PRINTER_INFO_0 *printer=NULL;
4670 WERROR result = WERR_OK;
4672 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4673 return WERR_NOMEM;
4675 construct_printer_info_0(print_hnd, printer, snum);
4677 /* check the required size. */
4678 *needed += spoolss_size_printer_info_0(printer);
4680 if (*needed > offered) {
4681 result = WERR_INSUFFICIENT_BUFFER;
4682 goto out;
4685 if (!rpcbuf_alloc_size(buffer, *needed)) {
4686 result = WERR_NOMEM;
4687 goto out;
4690 /* fill the buffer with the structures */
4691 smb_io_printer_info_0("", buffer, printer, 0);
4693 out:
4694 /* clear memory */
4696 SAFE_FREE(printer);
4698 return result;
4701 /****************************************************************************
4702 ****************************************************************************/
4704 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4706 PRINTER_INFO_1 *printer=NULL;
4707 WERROR result = WERR_OK;
4709 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4710 return WERR_NOMEM;
4712 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4714 /* check the required size. */
4715 *needed += spoolss_size_printer_info_1(printer);
4717 if (*needed > offered) {
4718 result = WERR_INSUFFICIENT_BUFFER;
4719 goto out;
4722 if (!rpcbuf_alloc_size(buffer, *needed)) {
4723 result = WERR_NOMEM;
4724 goto out;
4727 /* fill the buffer with the structures */
4728 smb_io_printer_info_1("", buffer, printer, 0);
4730 out:
4731 /* clear memory */
4732 SAFE_FREE(printer);
4734 return result;
4737 /****************************************************************************
4738 ****************************************************************************/
4740 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4742 PRINTER_INFO_2 *printer=NULL;
4743 WERROR result = WERR_OK;
4745 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4746 return WERR_NOMEM;
4748 construct_printer_info_2(print_hnd, printer, snum);
4750 /* check the required size. */
4751 *needed += spoolss_size_printer_info_2(printer);
4753 if (*needed > offered) {
4754 result = WERR_INSUFFICIENT_BUFFER;
4755 goto out;
4758 if (!rpcbuf_alloc_size(buffer, *needed)) {
4759 result = WERR_NOMEM;
4760 goto out;
4763 /* fill the buffer with the structures */
4764 if (!smb_io_printer_info_2("", buffer, printer, 0))
4765 result = WERR_NOMEM;
4767 out:
4768 /* clear memory */
4769 free_printer_info_2(printer);
4771 return result;
4774 /****************************************************************************
4775 ****************************************************************************/
4777 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4779 PRINTER_INFO_3 *printer=NULL;
4780 WERROR result = WERR_OK;
4782 if (!construct_printer_info_3(print_hnd, &printer, snum))
4783 return WERR_NOMEM;
4785 /* check the required size. */
4786 *needed += spoolss_size_printer_info_3(printer);
4788 if (*needed > offered) {
4789 result = WERR_INSUFFICIENT_BUFFER;
4790 goto out;
4793 if (!rpcbuf_alloc_size(buffer, *needed)) {
4794 result = WERR_NOMEM;
4795 goto out;
4798 /* fill the buffer with the structures */
4799 smb_io_printer_info_3("", buffer, printer, 0);
4801 out:
4802 /* clear memory */
4803 free_printer_info_3(printer);
4805 return result;
4808 /****************************************************************************
4809 ****************************************************************************/
4811 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4813 PRINTER_INFO_4 *printer=NULL;
4814 WERROR result = WERR_OK;
4816 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4817 return WERR_NOMEM;
4819 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4820 SAFE_FREE(printer);
4821 return WERR_NOMEM;
4824 /* check the required size. */
4825 *needed += spoolss_size_printer_info_4(printer);
4827 if (*needed > offered) {
4828 result = WERR_INSUFFICIENT_BUFFER;
4829 goto out;
4832 if (!rpcbuf_alloc_size(buffer, *needed)) {
4833 result = WERR_NOMEM;
4834 goto out;
4837 /* fill the buffer with the structures */
4838 smb_io_printer_info_4("", buffer, printer, 0);
4840 out:
4841 /* clear memory */
4842 free_printer_info_4(printer);
4844 return result;
4847 /****************************************************************************
4848 ****************************************************************************/
4850 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4852 PRINTER_INFO_5 *printer=NULL;
4853 WERROR result = WERR_OK;
4855 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4856 return WERR_NOMEM;
4858 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4859 free_printer_info_5(printer);
4860 return WERR_NOMEM;
4863 /* check the required size. */
4864 *needed += spoolss_size_printer_info_5(printer);
4866 if (*needed > offered) {
4867 result = WERR_INSUFFICIENT_BUFFER;
4868 goto out;
4871 if (!rpcbuf_alloc_size(buffer, *needed)) {
4872 result = WERR_NOMEM;
4873 goto out;
4876 /* fill the buffer with the structures */
4877 smb_io_printer_info_5("", buffer, printer, 0);
4879 out:
4880 /* clear memory */
4881 free_printer_info_5(printer);
4883 return result;
4886 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4888 PRINTER_INFO_7 *printer=NULL;
4889 WERROR result = WERR_OK;
4891 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4892 return WERR_NOMEM;
4894 if (!construct_printer_info_7(print_hnd, printer, snum))
4895 return WERR_NOMEM;
4897 /* check the required size. */
4898 *needed += spoolss_size_printer_info_7(printer);
4900 if (*needed > offered) {
4901 result = WERR_INSUFFICIENT_BUFFER;
4902 goto out;
4905 if (!rpcbuf_alloc_size(buffer, *needed)) {
4906 result = WERR_NOMEM;
4907 goto out;
4911 /* fill the buffer with the structures */
4912 smb_io_printer_info_7("", buffer, printer, 0);
4914 out:
4915 /* clear memory */
4916 free_printer_info_7(printer);
4918 return result;
4921 /****************************************************************************
4922 ****************************************************************************/
4924 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4926 POLICY_HND *handle = &q_u->handle;
4927 uint32 level = q_u->level;
4928 RPC_BUFFER *buffer = NULL;
4929 uint32 offered = q_u->offered;
4930 uint32 *needed = &r_u->needed;
4931 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4933 int snum;
4935 /* that's an [in out] buffer */
4937 if (!q_u->buffer && (offered!=0)) {
4938 return WERR_INVALID_PARAM;
4941 rpcbuf_move(q_u->buffer, &r_u->buffer);
4942 buffer = r_u->buffer;
4944 *needed=0;
4946 if (!get_printer_snum(p, handle, &snum))
4947 return WERR_BADFID;
4949 switch (level) {
4950 case 0:
4951 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4952 case 1:
4953 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4954 case 2:
4955 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4956 case 3:
4957 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4958 case 4:
4959 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4960 case 5:
4961 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4962 case 7:
4963 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4965 return WERR_UNKNOWN_LEVEL;
4968 /********************************************************************
4969 * fill a DRIVER_INFO_1 struct
4970 ********************************************************************/
4972 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4974 init_unistr( &info->name, driver.info_3->name);
4977 /********************************************************************
4978 * construct_printer_driver_info_1
4979 ********************************************************************/
4981 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4983 NT_PRINTER_INFO_LEVEL *printer = NULL;
4984 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4986 ZERO_STRUCT(driver);
4988 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4989 return WERR_INVALID_PRINTER_NAME;
4991 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4992 free_a_printer(&printer, 2);
4993 return WERR_UNKNOWN_PRINTER_DRIVER;
4996 fill_printer_driver_info_1(info, driver, servername, architecture);
4998 free_a_printer(&printer,2);
5000 return WERR_OK;
5003 /********************************************************************
5004 * construct_printer_driver_info_2
5005 * fill a printer_info_2 struct
5006 ********************************************************************/
5008 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5010 pstring temp;
5012 info->version=driver.info_3->cversion;
5014 init_unistr( &info->name, driver.info_3->name );
5015 init_unistr( &info->architecture, driver.info_3->environment );
5018 if (strlen(driver.info_3->driverpath)) {
5019 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5020 init_unistr( &info->driverpath, temp );
5021 } else
5022 init_unistr( &info->driverpath, "" );
5024 if (strlen(driver.info_3->datafile)) {
5025 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5026 init_unistr( &info->datafile, temp );
5027 } else
5028 init_unistr( &info->datafile, "" );
5030 if (strlen(driver.info_3->configfile)) {
5031 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5032 init_unistr( &info->configfile, temp );
5033 } else
5034 init_unistr( &info->configfile, "" );
5037 /********************************************************************
5038 * construct_printer_driver_info_2
5039 * fill a printer_info_2 struct
5040 ********************************************************************/
5042 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5044 NT_PRINTER_INFO_LEVEL *printer = NULL;
5045 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5047 ZERO_STRUCT(printer);
5048 ZERO_STRUCT(driver);
5050 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5051 return WERR_INVALID_PRINTER_NAME;
5053 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5054 free_a_printer(&printer, 2);
5055 return WERR_UNKNOWN_PRINTER_DRIVER;
5058 fill_printer_driver_info_2(info, driver, servername);
5060 free_a_printer(&printer,2);
5062 return WERR_OK;
5065 /********************************************************************
5066 * copy a strings array and convert to UNICODE
5068 * convert an array of ascii string to a UNICODE string
5069 ********************************************************************/
5071 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5073 int i=0;
5074 int j=0;
5075 const char *v;
5076 pstring line;
5078 DEBUG(6,("init_unistr_array\n"));
5079 *uni_array=NULL;
5081 while (True)
5083 if ( !char_array )
5084 v = "";
5085 else
5087 v = char_array[i];
5088 if (!v)
5089 v = ""; /* hack to handle null lists */
5092 /* hack to allow this to be used in places other than when generating
5093 the list of dependent files */
5095 if ( servername )
5096 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5097 else
5098 pstrcpy( line, v );
5100 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5102 /* add one extra unit16 for the second terminating NULL */
5104 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5105 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5106 return 0;
5109 if ( !strlen(v) )
5110 break;
5112 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5113 i++;
5116 if (*uni_array) {
5117 /* special case for ""; we need to add both NULL's here */
5118 if (!j)
5119 (*uni_array)[j++]=0x0000;
5120 (*uni_array)[j]=0x0000;
5123 DEBUGADD(6,("last one:done\n"));
5125 /* return size of array in uint16's */
5127 return j+1;
5130 /********************************************************************
5131 * construct_printer_info_3
5132 * fill a printer_info_3 struct
5133 ********************************************************************/
5135 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5137 pstring temp;
5139 ZERO_STRUCTP(info);
5141 info->version=driver.info_3->cversion;
5143 init_unistr( &info->name, driver.info_3->name );
5144 init_unistr( &info->architecture, driver.info_3->environment );
5146 if (strlen(driver.info_3->driverpath)) {
5147 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5148 init_unistr( &info->driverpath, temp );
5149 } else
5150 init_unistr( &info->driverpath, "" );
5152 if (strlen(driver.info_3->datafile)) {
5153 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5154 init_unistr( &info->datafile, temp );
5155 } else
5156 init_unistr( &info->datafile, "" );
5158 if (strlen(driver.info_3->configfile)) {
5159 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5160 init_unistr( &info->configfile, temp );
5161 } else
5162 init_unistr( &info->configfile, "" );
5164 if (strlen(driver.info_3->helpfile)) {
5165 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5166 init_unistr( &info->helpfile, temp );
5167 } else
5168 init_unistr( &info->helpfile, "" );
5170 init_unistr( &info->monitorname, driver.info_3->monitorname );
5171 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5173 info->dependentfiles=NULL;
5174 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5177 /********************************************************************
5178 * construct_printer_info_3
5179 * fill a printer_info_3 struct
5180 ********************************************************************/
5182 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5184 NT_PRINTER_INFO_LEVEL *printer = NULL;
5185 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5186 WERROR status;
5187 ZERO_STRUCT(driver);
5189 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5190 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5191 if (!W_ERROR_IS_OK(status))
5192 return WERR_INVALID_PRINTER_NAME;
5194 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5195 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5197 #if 0 /* JERRY */
5200 * I put this code in during testing. Helpful when commenting out the
5201 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5202 * as win2k always queries the driver using an infor level of 6.
5203 * I've left it in (but ifdef'd out) because I'll probably
5204 * use it in experimentation again in the future. --jerry 22/01/2002
5207 if (!W_ERROR_IS_OK(status)) {
5209 * Is this a W2k client ?
5211 if (version == 3) {
5212 /* Yes - try again with a WinNT driver. */
5213 version = 2;
5214 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5215 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5217 #endif
5219 if (!W_ERROR_IS_OK(status)) {
5220 free_a_printer(&printer,2);
5221 return WERR_UNKNOWN_PRINTER_DRIVER;
5224 #if 0 /* JERRY */
5226 #endif
5229 fill_printer_driver_info_3(info, driver, servername);
5231 free_a_printer(&printer,2);
5233 return WERR_OK;
5236 /********************************************************************
5237 * construct_printer_info_6
5238 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5239 ********************************************************************/
5241 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5243 pstring temp;
5244 fstring nullstr;
5246 ZERO_STRUCTP(info);
5247 memset(&nullstr, '\0', sizeof(fstring));
5249 info->version=driver.info_3->cversion;
5251 init_unistr( &info->name, driver.info_3->name );
5252 init_unistr( &info->architecture, driver.info_3->environment );
5254 if (strlen(driver.info_3->driverpath)) {
5255 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5256 init_unistr( &info->driverpath, temp );
5257 } else
5258 init_unistr( &info->driverpath, "" );
5260 if (strlen(driver.info_3->datafile)) {
5261 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5262 init_unistr( &info->datafile, temp );
5263 } else
5264 init_unistr( &info->datafile, "" );
5266 if (strlen(driver.info_3->configfile)) {
5267 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5268 init_unistr( &info->configfile, temp );
5269 } else
5270 init_unistr( &info->configfile, "" );
5272 if (strlen(driver.info_3->helpfile)) {
5273 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5274 init_unistr( &info->helpfile, temp );
5275 } else
5276 init_unistr( &info->helpfile, "" );
5278 init_unistr( &info->monitorname, driver.info_3->monitorname );
5279 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5281 info->dependentfiles = NULL;
5282 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5284 info->previousdrivernames=NULL;
5285 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5287 info->driver_date.low=0;
5288 info->driver_date.high=0;
5290 info->padding=0;
5291 info->driver_version_low=0;
5292 info->driver_version_high=0;
5294 init_unistr( &info->mfgname, "");
5295 init_unistr( &info->oem_url, "");
5296 init_unistr( &info->hardware_id, "");
5297 init_unistr( &info->provider, "");
5300 /********************************************************************
5301 * construct_printer_info_6
5302 * fill a printer_info_6 struct
5303 ********************************************************************/
5305 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5306 fstring servername, fstring architecture, uint32 version)
5308 NT_PRINTER_INFO_LEVEL *printer = NULL;
5309 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5310 WERROR status;
5312 ZERO_STRUCT(driver);
5314 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5316 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5318 if (!W_ERROR_IS_OK(status))
5319 return WERR_INVALID_PRINTER_NAME;
5321 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5323 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5325 if (!W_ERROR_IS_OK(status))
5328 * Is this a W2k client ?
5331 if (version < 3) {
5332 free_a_printer(&printer,2);
5333 return WERR_UNKNOWN_PRINTER_DRIVER;
5336 /* Yes - try again with a WinNT driver. */
5337 version = 2;
5338 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5339 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5340 if (!W_ERROR_IS_OK(status)) {
5341 free_a_printer(&printer,2);
5342 return WERR_UNKNOWN_PRINTER_DRIVER;
5346 fill_printer_driver_info_6(info, driver, servername);
5348 free_a_printer(&printer,2);
5349 free_a_printer_driver(driver, 3);
5351 return WERR_OK;
5354 /****************************************************************************
5355 ****************************************************************************/
5357 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5359 SAFE_FREE(info->dependentfiles);
5362 /****************************************************************************
5363 ****************************************************************************/
5365 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5367 SAFE_FREE(info->dependentfiles);
5370 /****************************************************************************
5371 ****************************************************************************/
5373 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5375 DRIVER_INFO_1 *info=NULL;
5376 WERROR result;
5378 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5379 return WERR_NOMEM;
5381 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5382 if (!W_ERROR_IS_OK(result))
5383 goto out;
5385 /* check the required size. */
5386 *needed += spoolss_size_printer_driver_info_1(info);
5388 if (*needed > offered) {
5389 result = WERR_INSUFFICIENT_BUFFER;
5390 goto out;
5393 if (!rpcbuf_alloc_size(buffer, *needed)) {
5394 result = WERR_NOMEM;
5395 goto out;
5398 /* fill the buffer with the structures */
5399 smb_io_printer_driver_info_1("", buffer, info, 0);
5401 out:
5402 /* clear memory */
5403 SAFE_FREE(info);
5405 return result;
5408 /****************************************************************************
5409 ****************************************************************************/
5411 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5413 DRIVER_INFO_2 *info=NULL;
5414 WERROR result;
5416 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5417 return WERR_NOMEM;
5419 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5420 if (!W_ERROR_IS_OK(result))
5421 goto out;
5423 /* check the required size. */
5424 *needed += spoolss_size_printer_driver_info_2(info);
5426 if (*needed > offered) {
5427 result = WERR_INSUFFICIENT_BUFFER;
5428 goto out;
5431 if (!rpcbuf_alloc_size(buffer, *needed)) {
5432 result = WERR_NOMEM;
5433 goto out;
5436 /* fill the buffer with the structures */
5437 smb_io_printer_driver_info_2("", buffer, info, 0);
5439 out:
5440 /* clear memory */
5441 SAFE_FREE(info);
5443 return result;
5446 /****************************************************************************
5447 ****************************************************************************/
5449 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5451 DRIVER_INFO_3 info;
5452 WERROR result;
5454 ZERO_STRUCT(info);
5456 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5457 if (!W_ERROR_IS_OK(result))
5458 goto out;
5460 /* check the required size. */
5461 *needed += spoolss_size_printer_driver_info_3(&info);
5463 if (*needed > offered) {
5464 result = WERR_INSUFFICIENT_BUFFER;
5465 goto out;
5468 if (!rpcbuf_alloc_size(buffer, *needed)) {
5469 result = WERR_NOMEM;
5470 goto out;
5473 /* fill the buffer with the structures */
5474 smb_io_printer_driver_info_3("", buffer, &info, 0);
5476 out:
5477 free_printer_driver_info_3(&info);
5479 return result;
5482 /****************************************************************************
5483 ****************************************************************************/
5485 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5487 DRIVER_INFO_6 info;
5488 WERROR result;
5490 ZERO_STRUCT(info);
5492 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5493 if (!W_ERROR_IS_OK(result))
5494 goto out;
5496 /* check the required size. */
5497 *needed += spoolss_size_printer_driver_info_6(&info);
5499 if (*needed > offered) {
5500 result = WERR_INSUFFICIENT_BUFFER;
5501 goto out;
5504 if (!rpcbuf_alloc_size(buffer, *needed)) {
5505 result = WERR_NOMEM;
5506 goto out;
5509 /* fill the buffer with the structures */
5510 smb_io_printer_driver_info_6("", buffer, &info, 0);
5512 out:
5513 free_printer_driver_info_6(&info);
5515 return result;
5518 /****************************************************************************
5519 ****************************************************************************/
5521 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5523 POLICY_HND *handle = &q_u->handle;
5524 UNISTR2 *uni_arch = &q_u->architecture;
5525 uint32 level = q_u->level;
5526 uint32 clientmajorversion = q_u->clientmajorversion;
5527 RPC_BUFFER *buffer = NULL;
5528 uint32 offered = q_u->offered;
5529 uint32 *needed = &r_u->needed;
5530 uint32 *servermajorversion = &r_u->servermajorversion;
5531 uint32 *serverminorversion = &r_u->serverminorversion;
5532 Printer_entry *printer;
5534 fstring servername;
5535 fstring architecture;
5536 int snum;
5538 /* that's an [in out] buffer */
5540 if (!q_u->buffer && (offered!=0)) {
5541 return WERR_INVALID_PARAM;
5544 rpcbuf_move(q_u->buffer, &r_u->buffer);
5545 buffer = r_u->buffer;
5547 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5549 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5550 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5551 return WERR_INVALID_PRINTER_NAME;
5554 *needed = 0;
5555 *servermajorversion = 0;
5556 *serverminorversion = 0;
5558 fstrcpy(servername, get_server_name( printer ));
5559 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5561 if (!get_printer_snum(p, handle, &snum))
5562 return WERR_BADFID;
5564 switch (level) {
5565 case 1:
5566 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5567 case 2:
5568 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5569 case 3:
5570 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5571 case 6:
5572 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5573 #if 0 /* JERRY */
5574 case 101:
5575 /* apparently this call is the equivalent of
5576 EnumPrinterDataEx() for the DsDriver key */
5577 break;
5578 #endif
5581 return WERR_UNKNOWN_LEVEL;
5584 /****************************************************************************
5585 ****************************************************************************/
5587 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5589 POLICY_HND *handle = &q_u->handle;
5591 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5593 if (!Printer) {
5594 DEBUG(3,("Error in startpageprinter printer handle\n"));
5595 return WERR_BADFID;
5598 Printer->page_started=True;
5599 return WERR_OK;
5602 /****************************************************************************
5603 ****************************************************************************/
5605 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5607 POLICY_HND *handle = &q_u->handle;
5608 int snum;
5610 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5612 if (!Printer) {
5613 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5614 return WERR_BADFID;
5617 if (!get_printer_snum(p, handle, &snum))
5618 return WERR_BADFID;
5620 Printer->page_started=False;
5621 print_job_endpage(snum, Printer->jobid);
5623 return WERR_OK;
5626 /********************************************************************
5627 * api_spoolss_getprinter
5628 * called from the spoolss dispatcher
5630 ********************************************************************/
5632 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5634 POLICY_HND *handle = &q_u->handle;
5635 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5636 uint32 *jobid = &r_u->jobid;
5638 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5639 int snum;
5640 pstring jobname;
5641 fstring datatype;
5642 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5644 if (!Printer) {
5645 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5646 return WERR_BADFID;
5650 * a nice thing with NT is it doesn't listen to what you tell it.
5651 * when asked to send _only_ RAW datas, it tries to send datas
5652 * in EMF format.
5654 * So I add checks like in NT Server ...
5657 if (info_1->p_datatype != 0) {
5658 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5659 if (strcmp(datatype, "RAW") != 0) {
5660 (*jobid)=0;
5661 return WERR_INVALID_DATATYPE;
5665 /* get the share number of the printer */
5666 if (!get_printer_snum(p, handle, &snum)) {
5667 return WERR_BADFID;
5670 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5672 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5674 /* An error occured in print_job_start() so return an appropriate
5675 NT error code. */
5677 if (Printer->jobid == -1) {
5678 return map_werror_from_unix(errno);
5681 Printer->document_started=True;
5682 (*jobid) = Printer->jobid;
5684 return WERR_OK;
5687 /********************************************************************
5688 * api_spoolss_getprinter
5689 * called from the spoolss dispatcher
5691 ********************************************************************/
5693 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5695 POLICY_HND *handle = &q_u->handle;
5697 return _spoolss_enddocprinter_internal(p, handle);
5700 /****************************************************************************
5701 ****************************************************************************/
5703 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5705 POLICY_HND *handle = &q_u->handle;
5706 uint32 buffer_size = q_u->buffer_size;
5707 uint8 *buffer = q_u->buffer;
5708 uint32 *buffer_written = &q_u->buffer_size2;
5709 int snum;
5710 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5712 if (!Printer) {
5713 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5714 r_u->buffer_written = q_u->buffer_size2;
5715 return WERR_BADFID;
5718 if (!get_printer_snum(p, handle, &snum))
5719 return WERR_BADFID;
5721 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5722 (SMB_OFF_T)-1, (size_t)buffer_size);
5723 if (*buffer_written == (uint32)-1) {
5724 r_u->buffer_written = 0;
5725 if (errno == ENOSPC)
5726 return WERR_NO_SPOOL_SPACE;
5727 else
5728 return WERR_ACCESS_DENIED;
5731 r_u->buffer_written = q_u->buffer_size2;
5733 return WERR_OK;
5736 /********************************************************************
5737 * api_spoolss_getprinter
5738 * called from the spoolss dispatcher
5740 ********************************************************************/
5742 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5743 pipes_struct *p)
5745 int snum;
5746 WERROR errcode = WERR_BADFUNC;
5747 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5749 if (!Printer) {
5750 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5751 return WERR_BADFID;
5754 if (!get_printer_snum(p, handle, &snum))
5755 return WERR_BADFID;
5757 switch (command) {
5758 case PRINTER_CONTROL_PAUSE:
5759 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5760 errcode = WERR_OK;
5762 break;
5763 case PRINTER_CONTROL_RESUME:
5764 case PRINTER_CONTROL_UNPAUSE:
5765 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5766 errcode = WERR_OK;
5768 break;
5769 case PRINTER_CONTROL_PURGE:
5770 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5771 errcode = WERR_OK;
5773 break;
5774 default:
5775 return WERR_UNKNOWN_LEVEL;
5778 return errcode;
5781 /********************************************************************
5782 * api_spoolss_abortprinter
5783 * From MSDN: "Deletes printer's spool file if printer is configured
5784 * for spooling"
5785 ********************************************************************/
5787 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5789 POLICY_HND *handle = &q_u->handle;
5790 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5791 int snum;
5792 WERROR errcode = WERR_OK;
5794 if (!Printer) {
5795 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5796 return WERR_BADFID;
5799 if (!get_printer_snum(p, handle, &snum))
5800 return WERR_BADFID;
5802 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5804 return errcode;
5807 /********************************************************************
5808 * called by spoolss_api_setprinter
5809 * when updating a printer description
5810 ********************************************************************/
5812 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5813 const SPOOL_PRINTER_INFO_LEVEL *info,
5814 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5816 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5817 WERROR result;
5818 int snum;
5820 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5822 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5823 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5824 OUR_HANDLE(handle)));
5826 result = WERR_BADFID;
5827 goto done;
5830 /* Check the user has permissions to change the security
5831 descriptor. By experimentation with two NT machines, the user
5832 requires Full Access to the printer to change security
5833 information. */
5835 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5836 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5837 result = WERR_ACCESS_DENIED;
5838 goto done;
5841 /* NT seems to like setting the security descriptor even though
5842 nothing may have actually changed. */
5844 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5846 if (DEBUGLEVEL >= 10) {
5847 SEC_ACL *the_acl;
5848 int i;
5850 the_acl = old_secdesc_ctr->sec->dacl;
5851 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5852 PRINTERNAME(snum), the_acl->num_aces));
5854 for (i = 0; i < the_acl->num_aces; i++) {
5855 fstring sid_str;
5857 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5859 DEBUG(10, ("%s 0x%08x\n", sid_str,
5860 the_acl->ace[i].info.mask));
5863 the_acl = secdesc_ctr->sec->dacl;
5865 if (the_acl) {
5866 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5867 PRINTERNAME(snum), the_acl->num_aces));
5869 for (i = 0; i < the_acl->num_aces; i++) {
5870 fstring sid_str;
5872 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5874 DEBUG(10, ("%s 0x%08x\n", sid_str,
5875 the_acl->ace[i].info.mask));
5877 } else {
5878 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5882 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5883 if (!new_secdesc_ctr) {
5884 result = WERR_NOMEM;
5885 goto done;
5888 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5889 result = WERR_OK;
5890 goto done;
5893 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5895 done:
5897 return result;
5900 /********************************************************************
5901 Canonicalize printer info from a client
5903 ATTN: It does not matter what we set the servername to hear
5904 since we do the necessary work in get_a_printer() to set it to
5905 the correct value based on what the client sent in the
5906 _spoolss_open_printer_ex().
5907 ********************************************************************/
5909 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5911 fstring printername;
5912 const char *p;
5914 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5915 "portname=%s drivername=%s comment=%s location=%s\n",
5916 info->servername, info->printername, info->sharename,
5917 info->portname, info->drivername, info->comment, info->location));
5919 /* we force some elements to "correct" values */
5920 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5921 fstrcpy(info->sharename, lp_servicename(snum));
5923 /* check to see if we allow printername != sharename */
5925 if ( lp_force_printername(snum) ) {
5926 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5927 global_myname(), info->sharename );
5928 } else {
5930 /* make sure printername is in \\server\printername format */
5932 fstrcpy( printername, info->printername );
5933 p = printername;
5934 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5935 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5936 p++;
5939 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5940 global_myname(), p );
5943 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5944 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5948 return True;
5951 /****************************************************************************
5952 ****************************************************************************/
5954 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5956 char *cmd = lp_addport_cmd();
5957 pstring command;
5958 int ret;
5959 int fd;
5960 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5961 BOOL is_print_op = False;
5963 if ( !*cmd ) {
5964 return WERR_ACCESS_DENIED;
5967 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5969 if ( token )
5970 is_print_op = user_has_privileges( token, &se_printop );
5972 DEBUG(10,("Running [%s]\n", command));
5974 /********* BEGIN SePrintOperatorPrivilege **********/
5976 if ( is_print_op )
5977 become_root();
5979 ret = smbrun(command, &fd);
5981 if ( is_print_op )
5982 unbecome_root();
5984 /********* END SePrintOperatorPrivilege **********/
5986 DEBUGADD(10,("returned [%d]\n", ret));
5988 if ( ret != 0 ) {
5989 if (fd != -1)
5990 close(fd);
5991 return WERR_ACCESS_DENIED;
5994 return WERR_OK;
5997 /****************************************************************************
5998 ****************************************************************************/
6000 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6002 char *cmd = lp_addprinter_cmd();
6003 char **qlines;
6004 pstring command;
6005 int numlines;
6006 int ret;
6007 int fd;
6008 fstring remote_machine = "%m";
6009 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6010 BOOL is_print_op = False;
6012 standard_sub_basic(current_user_info.smb_name,
6013 current_user_info.domain,
6014 remote_machine,sizeof(remote_machine));
6016 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6017 cmd, printer->info_2->printername, printer->info_2->sharename,
6018 printer->info_2->portname, printer->info_2->drivername,
6019 printer->info_2->location, printer->info_2->comment, remote_machine);
6021 if ( token )
6022 is_print_op = user_has_privileges( token, &se_printop );
6024 DEBUG(10,("Running [%s]\n", command));
6026 /********* BEGIN SePrintOperatorPrivilege **********/
6028 if ( is_print_op )
6029 become_root();
6031 if ( (ret = smbrun(command, &fd)) == 0 ) {
6032 /* Tell everyone we updated smb.conf. */
6033 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6036 if ( is_print_op )
6037 unbecome_root();
6039 /********* END SePrintOperatorPrivilege **********/
6041 DEBUGADD(10,("returned [%d]\n", ret));
6043 if ( ret != 0 ) {
6044 if (fd != -1)
6045 close(fd);
6046 return False;
6049 /* reload our services immediately */
6050 reload_services( False );
6052 numlines = 0;
6053 /* Get lines and convert them back to dos-codepage */
6054 qlines = fd_lines_load(fd, &numlines, 0);
6055 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6056 close(fd);
6058 /* Set the portname to what the script says the portname should be. */
6059 /* but don't require anything to be return from the script exit a good error code */
6061 if (numlines) {
6062 /* Set the portname to what the script says the portname should be. */
6063 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6064 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6067 file_lines_free(qlines);
6068 return True;
6072 /********************************************************************
6073 * Called by spoolss_api_setprinter
6074 * when updating a printer description.
6075 ********************************************************************/
6077 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6078 const SPOOL_PRINTER_INFO_LEVEL *info,
6079 DEVICEMODE *devmode)
6081 int snum;
6082 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6083 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6084 WERROR result;
6085 UNISTR2 buffer;
6086 fstring asc_buffer;
6088 DEBUG(8,("update_printer\n"));
6090 result = WERR_OK;
6092 if (!Printer) {
6093 result = WERR_BADFID;
6094 goto done;
6097 if (!get_printer_snum(p, handle, &snum)) {
6098 result = WERR_BADFID;
6099 goto done;
6102 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6103 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6104 result = WERR_BADFID;
6105 goto done;
6108 DEBUGADD(8,("Converting info_2 struct\n"));
6111 * convert_printer_info converts the incoming
6112 * info from the client and overwrites the info
6113 * just read from the tdb in the pointer 'printer'.
6116 if (!convert_printer_info(info, printer, level)) {
6117 result = WERR_NOMEM;
6118 goto done;
6121 if (devmode) {
6122 /* we have a valid devmode
6123 convert it and link it*/
6125 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6126 if (!convert_devicemode(printer->info_2->printername, devmode,
6127 &printer->info_2->devmode)) {
6128 result = WERR_NOMEM;
6129 goto done;
6133 /* Do sanity check on the requested changes for Samba */
6135 if (!check_printer_ok(printer->info_2, snum)) {
6136 result = WERR_INVALID_PARAM;
6137 goto done;
6140 /* FIXME!!! If the driver has changed we really should verify that
6141 it is installed before doing much else --jerry */
6143 /* Check calling user has permission to update printer description */
6145 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6146 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6147 result = WERR_ACCESS_DENIED;
6148 goto done;
6151 /* Call addprinter hook */
6152 /* Check changes to see if this is really needed */
6154 if ( *lp_addprinter_cmd()
6155 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6156 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6157 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6158 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6160 /* add_printer_hook() will call reload_services() */
6162 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6163 result = WERR_ACCESS_DENIED;
6164 goto done;
6169 * When a *new* driver is bound to a printer, the drivername is used to
6170 * lookup previously saved driver initialization info, which is then
6171 * bound to the printer, simulating what happens in the Windows arch.
6173 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6175 if (!set_driver_init(printer, 2))
6177 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6178 printer->info_2->drivername));
6181 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6182 printer->info_2->drivername));
6184 notify_printer_driver(snum, printer->info_2->drivername);
6188 * flag which changes actually occured. This is a small subset of
6189 * all the possible changes. We also have to update things in the
6190 * DsSpooler key.
6193 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6194 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6195 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6196 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6198 notify_printer_comment(snum, printer->info_2->comment);
6201 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6202 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6203 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6204 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6206 notify_printer_sharename(snum, printer->info_2->sharename);
6209 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6210 char *pname;
6212 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6213 pname++;
6214 else
6215 pname = printer->info_2->printername;
6218 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6219 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6220 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6222 notify_printer_printername( snum, pname );
6225 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6226 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6227 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6228 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6230 notify_printer_port(snum, printer->info_2->portname);
6233 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6234 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6235 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6236 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6238 notify_printer_location(snum, printer->info_2->location);
6241 /* here we need to update some more DsSpooler keys */
6242 /* uNCName, serverName, shortServerName */
6244 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6245 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6246 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6247 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6248 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6250 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6251 global_myname(), printer->info_2->sharename );
6252 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6253 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6254 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6256 /* Update printer info */
6257 result = mod_a_printer(printer, 2);
6259 done:
6260 free_a_printer(&printer, 2);
6261 free_a_printer(&old_printer, 2);
6264 return result;
6267 /****************************************************************************
6268 ****************************************************************************/
6269 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6270 const SPOOL_PRINTER_INFO_LEVEL *info)
6272 #ifdef HAVE_ADS
6273 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6274 int snum;
6275 Printer_entry *Printer;
6277 if ( lp_security() != SEC_ADS ) {
6278 return WERR_UNKNOWN_LEVEL;
6281 Printer = find_printer_index_by_hnd(p, handle);
6283 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6285 if (!Printer)
6286 return WERR_BADFID;
6288 if (!get_printer_snum(p, handle, &snum))
6289 return WERR_BADFID;
6291 nt_printer_publish(Printer, snum, info7->action);
6293 return WERR_OK;
6294 #else
6295 return WERR_UNKNOWN_LEVEL;
6296 #endif
6298 /****************************************************************************
6299 ****************************************************************************/
6301 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6303 POLICY_HND *handle = &q_u->handle;
6304 uint32 level = q_u->level;
6305 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6306 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6307 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6308 uint32 command = q_u->command;
6309 WERROR result;
6311 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6313 if (!Printer) {
6314 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6315 return WERR_BADFID;
6318 /* check the level */
6319 switch (level) {
6320 case 0:
6321 return control_printer(handle, command, p);
6322 case 2:
6323 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6324 if (!W_ERROR_IS_OK(result))
6325 return result;
6326 if (secdesc_ctr)
6327 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6328 return result;
6329 case 3:
6330 return update_printer_sec(handle, level, info, p,
6331 secdesc_ctr);
6332 case 7:
6333 return publish_or_unpublish_printer(p, handle, info);
6334 default:
6335 return WERR_UNKNOWN_LEVEL;
6339 /****************************************************************************
6340 ****************************************************************************/
6342 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6344 POLICY_HND *handle = &q_u->handle;
6345 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6347 if (!Printer) {
6348 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6349 return WERR_BADFID;
6352 if (Printer->notify.client_connected==True) {
6353 int snum = -1;
6355 if ( Printer->printer_type == SPLHND_SERVER)
6356 snum = -1;
6357 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6358 !get_printer_snum(p, handle, &snum) )
6359 return WERR_BADFID;
6361 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6364 Printer->notify.flags=0;
6365 Printer->notify.options=0;
6366 Printer->notify.localmachine[0]='\0';
6367 Printer->notify.printerlocal=0;
6368 if (Printer->notify.option)
6369 free_spool_notify_option(&Printer->notify.option);
6370 Printer->notify.client_connected=False;
6372 return WERR_OK;
6375 /****************************************************************************
6376 ****************************************************************************/
6378 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6380 /* that's an [in out] buffer */
6382 if (!q_u->buffer && (q_u->offered!=0)) {
6383 return WERR_INVALID_PARAM;
6386 rpcbuf_move(q_u->buffer, &r_u->buffer);
6388 r_u->needed = 0;
6389 return WERR_INVALID_PARAM; /* this is what a NT server
6390 returns for AddJob. AddJob
6391 must fail on non-local
6392 printers */
6395 /****************************************************************************
6396 ****************************************************************************/
6398 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6399 int position, int snum,
6400 NT_PRINTER_INFO_LEVEL *ntprinter)
6402 struct tm *t;
6404 t=gmtime(&queue->time);
6406 job_info->jobid=queue->job;
6407 init_unistr(&job_info->printername, lp_servicename(snum));
6408 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6409 init_unistr(&job_info->username, queue->fs_user);
6410 init_unistr(&job_info->document, queue->fs_file);
6411 init_unistr(&job_info->datatype, "RAW");
6412 init_unistr(&job_info->text_status, "");
6413 job_info->status=nt_printj_status(queue->status);
6414 job_info->priority=queue->priority;
6415 job_info->position=position;
6416 job_info->totalpages=queue->page_count;
6417 job_info->pagesprinted=0;
6419 make_systemtime(&job_info->submitted, t);
6422 /****************************************************************************
6423 ****************************************************************************/
6425 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6426 int position, int snum,
6427 NT_PRINTER_INFO_LEVEL *ntprinter,
6428 DEVICEMODE *devmode)
6430 struct tm *t;
6432 t=gmtime(&queue->time);
6434 job_info->jobid=queue->job;
6436 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6438 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6439 init_unistr(&job_info->username, queue->fs_user);
6440 init_unistr(&job_info->document, queue->fs_file);
6441 init_unistr(&job_info->notifyname, queue->fs_user);
6442 init_unistr(&job_info->datatype, "RAW");
6443 init_unistr(&job_info->printprocessor, "winprint");
6444 init_unistr(&job_info->parameters, "");
6445 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6446 init_unistr(&job_info->text_status, "");
6448 /* and here the security descriptor */
6450 job_info->status=nt_printj_status(queue->status);
6451 job_info->priority=queue->priority;
6452 job_info->position=position;
6453 job_info->starttime=0;
6454 job_info->untiltime=0;
6455 job_info->totalpages=queue->page_count;
6456 job_info->size=queue->size;
6457 make_systemtime(&(job_info->submitted), t);
6458 job_info->timeelapsed=0;
6459 job_info->pagesprinted=0;
6461 job_info->devmode = devmode;
6463 return (True);
6466 /****************************************************************************
6467 Enumjobs at level 1.
6468 ****************************************************************************/
6470 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6471 NT_PRINTER_INFO_LEVEL *ntprinter,
6472 RPC_BUFFER *buffer, uint32 offered,
6473 uint32 *needed, uint32 *returned)
6475 JOB_INFO_1 *info;
6476 int i;
6477 WERROR result = WERR_OK;
6479 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6480 if (info==NULL) {
6481 SAFE_FREE(queue);
6482 *returned=0;
6483 return WERR_NOMEM;
6486 for (i=0; i<*returned; i++)
6487 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6489 SAFE_FREE(queue);
6491 /* check the required size. */
6492 for (i=0; i<*returned; i++)
6493 (*needed) += spoolss_size_job_info_1(&info[i]);
6495 if (*needed > offered) {
6496 result = WERR_INSUFFICIENT_BUFFER;
6497 goto out;
6500 if (!rpcbuf_alloc_size(buffer, *needed)) {
6501 result = WERR_NOMEM;
6502 goto out;
6505 /* fill the buffer with the structures */
6506 for (i=0; i<*returned; i++)
6507 smb_io_job_info_1("", buffer, &info[i], 0);
6509 out:
6510 /* clear memory */
6511 SAFE_FREE(info);
6513 if ( !W_ERROR_IS_OK(result) )
6514 *returned = 0;
6516 return result;
6519 /****************************************************************************
6520 Enumjobs at level 2.
6521 ****************************************************************************/
6523 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6524 NT_PRINTER_INFO_LEVEL *ntprinter,
6525 RPC_BUFFER *buffer, uint32 offered,
6526 uint32 *needed, uint32 *returned)
6528 JOB_INFO_2 *info = NULL;
6529 int i;
6530 WERROR result = WERR_OK;
6531 DEVICEMODE *devmode = NULL;
6533 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6534 *returned=0;
6535 return WERR_NOMEM;
6538 /* this should not be a failure condition if the devmode is NULL */
6540 devmode = construct_dev_mode(lp_const_servicename(snum));
6542 for (i=0; i<*returned; i++)
6543 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6545 free_a_printer(&ntprinter, 2);
6546 SAFE_FREE(queue);
6548 /* check the required size. */
6549 for (i=0; i<*returned; i++)
6550 (*needed) += spoolss_size_job_info_2(&info[i]);
6552 if (*needed > offered) {
6553 result = WERR_INSUFFICIENT_BUFFER;
6554 goto out;
6557 if (!rpcbuf_alloc_size(buffer, *needed)) {
6558 result = WERR_NOMEM;
6559 goto out;
6562 /* fill the buffer with the structures */
6563 for (i=0; i<*returned; i++)
6564 smb_io_job_info_2("", buffer, &info[i], 0);
6566 out:
6567 free_devmode(devmode);
6568 SAFE_FREE(info);
6570 if ( !W_ERROR_IS_OK(result) )
6571 *returned = 0;
6573 return result;
6577 /****************************************************************************
6578 Enumjobs.
6579 ****************************************************************************/
6581 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6583 POLICY_HND *handle = &q_u->handle;
6584 uint32 level = q_u->level;
6585 RPC_BUFFER *buffer = NULL;
6586 uint32 offered = q_u->offered;
6587 uint32 *needed = &r_u->needed;
6588 uint32 *returned = &r_u->returned;
6589 WERROR wret;
6590 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6591 int snum;
6592 print_status_struct prt_status;
6593 print_queue_struct *queue=NULL;
6595 /* that's an [in out] buffer */
6597 if (!q_u->buffer && (offered!=0)) {
6598 return WERR_INVALID_PARAM;
6601 rpcbuf_move(q_u->buffer, &r_u->buffer);
6602 buffer = r_u->buffer;
6604 DEBUG(4,("_spoolss_enumjobs\n"));
6606 *needed=0;
6607 *returned=0;
6609 /* lookup the printer snum and tdb entry */
6611 if (!get_printer_snum(p, handle, &snum))
6612 return WERR_BADFID;
6614 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6615 if ( !W_ERROR_IS_OK(wret) )
6616 return wret;
6618 *returned = print_queue_status(snum, &queue, &prt_status);
6619 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6621 if (*returned == 0) {
6622 SAFE_FREE(queue);
6623 free_a_printer(&ntprinter, 2);
6624 return WERR_OK;
6627 switch (level) {
6628 case 1:
6629 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6630 break;
6631 case 2:
6632 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6633 break;
6634 default:
6635 *returned=0;
6636 wret = WERR_UNKNOWN_LEVEL;
6637 break;
6640 SAFE_FREE(queue);
6641 free_a_printer( &ntprinter, 2 );
6642 return wret;
6645 /****************************************************************************
6646 ****************************************************************************/
6648 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6650 return WERR_OK;
6653 /****************************************************************************
6654 ****************************************************************************/
6656 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6658 POLICY_HND *handle = &q_u->handle;
6659 uint32 jobid = q_u->jobid;
6660 uint32 command = q_u->command;
6662 int snum;
6663 WERROR errcode = WERR_BADFUNC;
6665 if (!get_printer_snum(p, handle, &snum)) {
6666 return WERR_BADFID;
6669 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6670 return WERR_INVALID_PRINTER_NAME;
6673 switch (command) {
6674 case JOB_CONTROL_CANCEL:
6675 case JOB_CONTROL_DELETE:
6676 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6677 errcode = WERR_OK;
6679 break;
6680 case JOB_CONTROL_PAUSE:
6681 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6682 errcode = WERR_OK;
6684 break;
6685 case JOB_CONTROL_RESTART:
6686 case JOB_CONTROL_RESUME:
6687 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6688 errcode = WERR_OK;
6690 break;
6691 default:
6692 return WERR_UNKNOWN_LEVEL;
6695 return errcode;
6698 /****************************************************************************
6699 Enumerates all printer drivers at level 1.
6700 ****************************************************************************/
6702 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6704 int i;
6705 int ndrivers;
6706 uint32 version;
6707 fstring *list = NULL;
6708 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6709 DRIVER_INFO_1 *driver_info_1=NULL;
6710 WERROR result = WERR_OK;
6712 *returned=0;
6714 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6715 list=NULL;
6716 ndrivers=get_ntdrivers(&list, architecture, version);
6717 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6719 if(ndrivers == -1) {
6720 SAFE_FREE(driver_info_1);
6721 return WERR_NOMEM;
6724 if(ndrivers != 0) {
6725 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6726 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6727 SAFE_FREE(list);
6728 return WERR_NOMEM;
6732 for (i=0; i<ndrivers; i++) {
6733 WERROR status;
6734 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6735 ZERO_STRUCT(driver);
6736 status = get_a_printer_driver(&driver, 3, list[i],
6737 architecture, version);
6738 if (!W_ERROR_IS_OK(status)) {
6739 SAFE_FREE(list);
6740 SAFE_FREE(driver_info_1);
6741 return status;
6743 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6744 free_a_printer_driver(driver, 3);
6747 *returned+=ndrivers;
6748 SAFE_FREE(list);
6751 /* check the required size. */
6752 for (i=0; i<*returned; i++) {
6753 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6754 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6757 if (*needed > offered) {
6758 result = WERR_INSUFFICIENT_BUFFER;
6759 goto out;
6762 if (!rpcbuf_alloc_size(buffer, *needed)) {
6763 result = WERR_NOMEM;
6764 goto out;
6767 /* fill the buffer with the driver structures */
6768 for (i=0; i<*returned; i++) {
6769 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6770 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6773 out:
6774 SAFE_FREE(driver_info_1);
6776 if ( !W_ERROR_IS_OK(result) )
6777 *returned = 0;
6779 return result;
6782 /****************************************************************************
6783 Enumerates all printer drivers at level 2.
6784 ****************************************************************************/
6786 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6788 int i;
6789 int ndrivers;
6790 uint32 version;
6791 fstring *list = NULL;
6792 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6793 DRIVER_INFO_2 *driver_info_2=NULL;
6794 WERROR result = WERR_OK;
6796 *returned=0;
6798 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6799 list=NULL;
6800 ndrivers=get_ntdrivers(&list, architecture, version);
6801 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6803 if(ndrivers == -1) {
6804 SAFE_FREE(driver_info_2);
6805 return WERR_NOMEM;
6808 if(ndrivers != 0) {
6809 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6810 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6811 SAFE_FREE(list);
6812 return WERR_NOMEM;
6816 for (i=0; i<ndrivers; i++) {
6817 WERROR status;
6819 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6820 ZERO_STRUCT(driver);
6821 status = get_a_printer_driver(&driver, 3, list[i],
6822 architecture, version);
6823 if (!W_ERROR_IS_OK(status)) {
6824 SAFE_FREE(list);
6825 SAFE_FREE(driver_info_2);
6826 return status;
6828 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6829 free_a_printer_driver(driver, 3);
6832 *returned+=ndrivers;
6833 SAFE_FREE(list);
6836 /* check the required size. */
6837 for (i=0; i<*returned; i++) {
6838 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6839 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6842 if (*needed > offered) {
6843 result = WERR_INSUFFICIENT_BUFFER;
6844 goto out;
6847 if (!rpcbuf_alloc_size(buffer, *needed)) {
6848 result = WERR_NOMEM;
6849 goto out;
6852 /* fill the buffer with the form structures */
6853 for (i=0; i<*returned; i++) {
6854 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6855 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6858 out:
6859 SAFE_FREE(driver_info_2);
6861 if ( !W_ERROR_IS_OK(result) )
6862 *returned = 0;
6864 return result;
6867 /****************************************************************************
6868 Enumerates all printer drivers at level 3.
6869 ****************************************************************************/
6871 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6873 int i;
6874 int ndrivers;
6875 uint32 version;
6876 fstring *list = NULL;
6877 DRIVER_INFO_3 *driver_info_3=NULL;
6878 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6879 WERROR result = WERR_OK;
6881 *returned=0;
6883 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6884 list=NULL;
6885 ndrivers=get_ntdrivers(&list, architecture, version);
6886 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6888 if(ndrivers == -1) {
6889 SAFE_FREE(driver_info_3);
6890 return WERR_NOMEM;
6893 if(ndrivers != 0) {
6894 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6895 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6896 SAFE_FREE(list);
6897 return WERR_NOMEM;
6901 for (i=0; i<ndrivers; i++) {
6902 WERROR status;
6904 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6905 ZERO_STRUCT(driver);
6906 status = get_a_printer_driver(&driver, 3, list[i],
6907 architecture, version);
6908 if (!W_ERROR_IS_OK(status)) {
6909 SAFE_FREE(list);
6910 SAFE_FREE(driver_info_3);
6911 return status;
6913 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6914 free_a_printer_driver(driver, 3);
6917 *returned+=ndrivers;
6918 SAFE_FREE(list);
6921 /* check the required size. */
6922 for (i=0; i<*returned; i++) {
6923 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6924 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6927 if (*needed > offered) {
6928 result = WERR_INSUFFICIENT_BUFFER;
6929 goto out;
6932 if (!rpcbuf_alloc_size(buffer, *needed)) {
6933 result = WERR_NOMEM;
6934 goto out;
6937 /* fill the buffer with the driver structures */
6938 for (i=0; i<*returned; i++) {
6939 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6940 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6943 out:
6944 for (i=0; i<*returned; i++) {
6945 SAFE_FREE(driver_info_3[i].dependentfiles);
6948 SAFE_FREE(driver_info_3);
6950 if ( !W_ERROR_IS_OK(result) )
6951 *returned = 0;
6953 return result;
6956 /****************************************************************************
6957 Enumerates all printer drivers.
6958 ****************************************************************************/
6960 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6962 uint32 level = q_u->level;
6963 RPC_BUFFER *buffer = NULL;
6964 uint32 offered = q_u->offered;
6965 uint32 *needed = &r_u->needed;
6966 uint32 *returned = &r_u->returned;
6968 fstring servername;
6969 fstring architecture;
6971 /* that's an [in out] buffer */
6973 if (!q_u->buffer && (offered!=0)) {
6974 return WERR_INVALID_PARAM;
6977 rpcbuf_move(q_u->buffer, &r_u->buffer);
6978 buffer = r_u->buffer;
6980 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6982 *needed = 0;
6983 *returned = 0;
6985 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6986 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6988 if ( !is_myname_or_ipaddr( servername ) )
6989 return WERR_UNKNOWN_PRINTER_DRIVER;
6991 switch (level) {
6992 case 1:
6993 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6994 case 2:
6995 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6996 case 3:
6997 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6998 default:
6999 return WERR_UNKNOWN_LEVEL;
7003 /****************************************************************************
7004 ****************************************************************************/
7006 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7008 form->flag=list->flag;
7009 init_unistr(&form->name, list->name);
7010 form->width=list->width;
7011 form->length=list->length;
7012 form->left=list->left;
7013 form->top=list->top;
7014 form->right=list->right;
7015 form->bottom=list->bottom;
7018 /****************************************************************************
7019 ****************************************************************************/
7021 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7023 uint32 level = q_u->level;
7024 RPC_BUFFER *buffer = NULL;
7025 uint32 offered = q_u->offered;
7026 uint32 *needed = &r_u->needed;
7027 uint32 *numofforms = &r_u->numofforms;
7028 uint32 numbuiltinforms;
7030 nt_forms_struct *list=NULL;
7031 nt_forms_struct *builtinlist=NULL;
7032 FORM_1 *forms_1;
7033 int buffer_size=0;
7034 int i;
7036 /* that's an [in out] buffer */
7038 if (!q_u->buffer && (offered!=0) ) {
7039 return WERR_INVALID_PARAM;
7042 rpcbuf_move(q_u->buffer, &r_u->buffer);
7043 buffer = r_u->buffer;
7045 DEBUG(4,("_spoolss_enumforms\n"));
7046 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7047 DEBUGADD(5,("Info level [%d]\n", level));
7049 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7050 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7051 *numofforms = get_ntforms(&list);
7052 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7053 *numofforms += numbuiltinforms;
7055 if (*numofforms == 0) {
7056 SAFE_FREE(builtinlist);
7057 SAFE_FREE(list);
7058 return WERR_NO_MORE_ITEMS;
7061 switch (level) {
7062 case 1:
7063 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7064 SAFE_FREE(builtinlist);
7065 SAFE_FREE(list);
7066 *numofforms=0;
7067 return WERR_NOMEM;
7070 /* construct the list of form structures */
7071 for (i=0; i<numbuiltinforms; i++) {
7072 DEBUGADD(6,("Filling form number [%d]\n",i));
7073 fill_form_1(&forms_1[i], &builtinlist[i]);
7076 SAFE_FREE(builtinlist);
7078 for (; i<*numofforms; i++) {
7079 DEBUGADD(6,("Filling form number [%d]\n",i));
7080 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7083 SAFE_FREE(list);
7085 /* check the required size. */
7086 for (i=0; i<numbuiltinforms; i++) {
7087 DEBUGADD(6,("adding form [%d]'s size\n",i));
7088 buffer_size += spoolss_size_form_1(&forms_1[i]);
7090 for (; i<*numofforms; i++) {
7091 DEBUGADD(6,("adding form [%d]'s size\n",i));
7092 buffer_size += spoolss_size_form_1(&forms_1[i]);
7095 *needed=buffer_size;
7097 if (*needed > offered) {
7098 SAFE_FREE(forms_1);
7099 *numofforms=0;
7100 return WERR_INSUFFICIENT_BUFFER;
7103 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7104 SAFE_FREE(forms_1);
7105 *numofforms=0;
7106 return WERR_NOMEM;
7109 /* fill the buffer with the form structures */
7110 for (i=0; i<numbuiltinforms; i++) {
7111 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7112 smb_io_form_1("", buffer, &forms_1[i], 0);
7114 for (; i<*numofforms; i++) {
7115 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7116 smb_io_form_1("", buffer, &forms_1[i], 0);
7119 SAFE_FREE(forms_1);
7121 return WERR_OK;
7123 default:
7124 SAFE_FREE(list);
7125 SAFE_FREE(builtinlist);
7126 return WERR_UNKNOWN_LEVEL;
7130 /****************************************************************************
7131 ****************************************************************************/
7133 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7135 uint32 level = q_u->level;
7136 UNISTR2 *uni_formname = &q_u->formname;
7137 RPC_BUFFER *buffer = NULL;
7138 uint32 offered = q_u->offered;
7139 uint32 *needed = &r_u->needed;
7141 nt_forms_struct *list=NULL;
7142 nt_forms_struct builtin_form;
7143 BOOL foundBuiltin;
7144 FORM_1 form_1;
7145 fstring form_name;
7146 int buffer_size=0;
7147 int numofforms=0, i=0;
7149 /* that's an [in out] buffer */
7151 if (!q_u->buffer && (offered!=0)) {
7152 return WERR_INVALID_PARAM;
7155 rpcbuf_move(q_u->buffer, &r_u->buffer);
7156 buffer = r_u->buffer;
7158 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7160 DEBUG(4,("_spoolss_getform\n"));
7161 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7162 DEBUGADD(5,("Info level [%d]\n", level));
7164 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7165 if (!foundBuiltin) {
7166 numofforms = get_ntforms(&list);
7167 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7169 if (numofforms == 0)
7170 return WERR_BADFID;
7173 switch (level) {
7174 case 1:
7175 if (foundBuiltin) {
7176 fill_form_1(&form_1, &builtin_form);
7177 } else {
7179 /* Check if the requested name is in the list of form structures */
7180 for (i=0; i<numofforms; i++) {
7182 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7184 if (strequal(form_name, list[i].name)) {
7185 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7186 fill_form_1(&form_1, &list[i]);
7187 break;
7191 SAFE_FREE(list);
7192 if (i == numofforms) {
7193 return WERR_BADFID;
7196 /* check the required size. */
7198 *needed=spoolss_size_form_1(&form_1);
7200 if (*needed > offered)
7201 return WERR_INSUFFICIENT_BUFFER;
7203 if (!rpcbuf_alloc_size(buffer, buffer_size))
7204 return WERR_NOMEM;
7206 /* fill the buffer with the form structures */
7207 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7208 smb_io_form_1("", buffer, &form_1, 0);
7210 return WERR_OK;
7212 default:
7213 SAFE_FREE(list);
7214 return WERR_UNKNOWN_LEVEL;
7218 /****************************************************************************
7219 ****************************************************************************/
7221 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7223 init_unistr(&port->port_name, name);
7226 /****************************************************************************
7227 TODO: This probably needs distinguish between TCP/IP and Local ports
7228 somehow.
7229 ****************************************************************************/
7231 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7233 init_unistr(&port->port_name, name);
7234 init_unistr(&port->monitor_name, "Local Monitor");
7235 init_unistr(&port->description, SPL_LOCAL_PORT );
7236 port->port_type=PORT_TYPE_WRITE;
7237 port->reserved=0x0;
7241 /****************************************************************************
7242 wrapper around the enumer ports command
7243 ****************************************************************************/
7245 WERROR enumports_hook( int *count, char ***lines )
7247 char *cmd = lp_enumports_cmd();
7248 char **qlines;
7249 pstring command;
7250 int numlines;
7251 int ret;
7252 int fd;
7254 *count = 0;
7255 *lines = NULL;
7257 /* if no hook then just fill in the default port */
7259 if ( !*cmd ) {
7260 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7261 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7262 qlines[1] = NULL;
7263 numlines = 1;
7265 else {
7266 /* we have a valid enumport command */
7268 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7270 DEBUG(10,("Running [%s]\n", command));
7271 ret = smbrun(command, &fd);
7272 DEBUG(10,("Returned [%d]\n", ret));
7273 if (ret != 0) {
7274 if (fd != -1) {
7275 close(fd);
7277 return WERR_ACCESS_DENIED;
7280 numlines = 0;
7281 qlines = fd_lines_load(fd, &numlines, 0);
7282 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7283 close(fd);
7286 *count = numlines;
7287 *lines = qlines;
7289 return WERR_OK;
7292 /****************************************************************************
7293 enumports level 1.
7294 ****************************************************************************/
7296 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7298 PORT_INFO_1 *ports=NULL;
7299 int i=0;
7300 WERROR result = WERR_OK;
7301 char **qlines = NULL;
7302 int numlines = 0;
7304 result = enumports_hook( &numlines, &qlines );
7305 if (!W_ERROR_IS_OK(result)) {
7306 file_lines_free(qlines);
7307 return result;
7310 if(numlines) {
7311 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7312 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7313 dos_errstr(WERR_NOMEM)));
7314 file_lines_free(qlines);
7315 return WERR_NOMEM;
7318 for (i=0; i<numlines; i++) {
7319 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7320 fill_port_1(&ports[i], qlines[i]);
7323 file_lines_free(qlines);
7325 *returned = numlines;
7327 /* check the required size. */
7328 for (i=0; i<*returned; i++) {
7329 DEBUGADD(6,("adding port [%d]'s size\n", i));
7330 *needed += spoolss_size_port_info_1(&ports[i]);
7333 if (*needed > offered) {
7334 result = WERR_INSUFFICIENT_BUFFER;
7335 goto out;
7338 if (!rpcbuf_alloc_size(buffer, *needed)) {
7339 result = WERR_NOMEM;
7340 goto out;
7343 /* fill the buffer with the ports structures */
7344 for (i=0; i<*returned; i++) {
7345 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7346 smb_io_port_1("", buffer, &ports[i], 0);
7349 out:
7350 SAFE_FREE(ports);
7352 if ( !W_ERROR_IS_OK(result) )
7353 *returned = 0;
7355 return result;
7358 /****************************************************************************
7359 enumports level 2.
7360 ****************************************************************************/
7362 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7364 PORT_INFO_2 *ports=NULL;
7365 int i=0;
7366 WERROR result = WERR_OK;
7367 char **qlines = NULL;
7368 int numlines = 0;
7370 result = enumports_hook( &numlines, &qlines );
7371 if ( !W_ERROR_IS_OK(result)) {
7372 file_lines_free(qlines);
7373 return result;
7376 if(numlines) {
7377 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7378 file_lines_free(qlines);
7379 return WERR_NOMEM;
7382 for (i=0; i<numlines; i++) {
7383 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7384 fill_port_2(&(ports[i]), qlines[i]);
7388 file_lines_free(qlines);
7390 *returned = numlines;
7392 /* check the required size. */
7393 for (i=0; i<*returned; i++) {
7394 DEBUGADD(6,("adding port [%d]'s size\n", i));
7395 *needed += spoolss_size_port_info_2(&ports[i]);
7398 if (*needed > offered) {
7399 result = WERR_INSUFFICIENT_BUFFER;
7400 goto out;
7403 if (!rpcbuf_alloc_size(buffer, *needed)) {
7404 result = WERR_NOMEM;
7405 goto out;
7408 /* fill the buffer with the ports structures */
7409 for (i=0; i<*returned; i++) {
7410 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7411 smb_io_port_2("", buffer, &ports[i], 0);
7414 out:
7415 SAFE_FREE(ports);
7417 if ( !W_ERROR_IS_OK(result) )
7418 *returned = 0;
7420 return result;
7423 /****************************************************************************
7424 enumports.
7425 ****************************************************************************/
7427 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7429 uint32 level = q_u->level;
7430 RPC_BUFFER *buffer = NULL;
7431 uint32 offered = q_u->offered;
7432 uint32 *needed = &r_u->needed;
7433 uint32 *returned = &r_u->returned;
7435 /* that's an [in out] buffer */
7437 if (!q_u->buffer && (offered!=0)) {
7438 return WERR_INVALID_PARAM;
7441 rpcbuf_move(q_u->buffer, &r_u->buffer);
7442 buffer = r_u->buffer;
7444 DEBUG(4,("_spoolss_enumports\n"));
7446 *returned=0;
7447 *needed=0;
7449 switch (level) {
7450 case 1:
7451 return enumports_level_1(buffer, offered, needed, returned);
7452 case 2:
7453 return enumports_level_2(buffer, offered, needed, returned);
7454 default:
7455 return WERR_UNKNOWN_LEVEL;
7459 /****************************************************************************
7460 ****************************************************************************/
7462 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7463 const SPOOL_PRINTER_INFO_LEVEL *info,
7464 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7465 uint32 user_switch, const SPOOL_USER_CTR *user,
7466 POLICY_HND *handle)
7468 NT_PRINTER_INFO_LEVEL *printer = NULL;
7469 fstring name;
7470 int snum;
7471 WERROR err = WERR_OK;
7473 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7474 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7475 return WERR_NOMEM;
7478 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7479 if (!convert_printer_info(info, printer, 2)) {
7480 free_a_printer(&printer, 2);
7481 return WERR_NOMEM;
7484 /* check to see if the printer already exists */
7486 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7487 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7488 printer->info_2->sharename));
7489 free_a_printer(&printer, 2);
7490 return WERR_PRINTER_ALREADY_EXISTS;
7493 /* FIXME!!! smbd should check to see if the driver is installed before
7494 trying to add a printer like this --jerry */
7496 if (*lp_addprinter_cmd() ) {
7497 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7498 free_a_printer(&printer,2);
7499 return WERR_ACCESS_DENIED;
7501 } else {
7502 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7503 "smb.conf parameter \"addprinter command\" is defined. This"
7504 "parameter must exist for this call to succeed\n",
7505 printer->info_2->sharename ));
7508 /* use our primary netbios name since get_a_printer() will convert
7509 it to what the client expects on a case by case basis */
7511 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7512 printer->info_2->sharename);
7515 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7516 free_a_printer(&printer,2);
7517 return WERR_ACCESS_DENIED;
7520 /* you must be a printer admin to add a new printer */
7521 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7522 free_a_printer(&printer,2);
7523 return WERR_ACCESS_DENIED;
7527 * Do sanity check on the requested changes for Samba.
7530 if (!check_printer_ok(printer->info_2, snum)) {
7531 free_a_printer(&printer,2);
7532 return WERR_INVALID_PARAM;
7536 * When a printer is created, the drivername bound to the printer is used
7537 * to lookup previously saved driver initialization info, which is then
7538 * bound to the new printer, simulating what happens in the Windows arch.
7541 if (!devmode)
7543 set_driver_init(printer, 2);
7545 else
7547 /* A valid devmode was included, convert and link it
7549 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7551 if (!convert_devicemode(printer->info_2->printername, devmode,
7552 &printer->info_2->devmode))
7553 return WERR_NOMEM;
7556 /* write the ASCII on disk */
7557 err = mod_a_printer(printer, 2);
7558 if (!W_ERROR_IS_OK(err)) {
7559 free_a_printer(&printer,2);
7560 return err;
7563 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7564 /* Handle open failed - remove addition. */
7565 del_a_printer(printer->info_2->sharename);
7566 free_a_printer(&printer,2);
7567 return WERR_ACCESS_DENIED;
7570 update_c_setprinter(False);
7571 free_a_printer(&printer,2);
7573 return WERR_OK;
7576 /****************************************************************************
7577 ****************************************************************************/
7579 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7581 UNISTR2 *uni_srv_name = q_u->server_name;
7582 uint32 level = q_u->level;
7583 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7584 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7585 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7586 uint32 user_switch = q_u->user_switch;
7587 SPOOL_USER_CTR *user = &q_u->user_ctr;
7588 POLICY_HND *handle = &r_u->handle;
7590 switch (level) {
7591 case 1:
7592 /* we don't handle yet */
7593 /* but I know what to do ... */
7594 return WERR_UNKNOWN_LEVEL;
7595 case 2:
7596 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7597 devmode, sdb,
7598 user_switch, user, handle);
7599 default:
7600 return WERR_UNKNOWN_LEVEL;
7604 /****************************************************************************
7605 ****************************************************************************/
7607 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7609 uint32 level = q_u->level;
7610 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7611 WERROR err = WERR_OK;
7612 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7613 fstring driver_name;
7614 uint32 version;
7616 ZERO_STRUCT(driver);
7618 if (!convert_printer_driver_info(info, &driver, level)) {
7619 err = WERR_NOMEM;
7620 goto done;
7623 DEBUG(5,("Cleaning driver's information\n"));
7624 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7625 if (!W_ERROR_IS_OK(err))
7626 goto done;
7628 DEBUG(5,("Moving driver to final destination\n"));
7629 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7630 goto done;
7633 if (add_a_printer_driver(driver, level)!=0) {
7634 err = WERR_ACCESS_DENIED;
7635 goto done;
7639 * I think this is where he DrvUpgradePrinter() hook would be
7640 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7641 * server. Right now, we just need to send ourselves a message
7642 * to update each printer bound to this driver. --jerry
7645 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7646 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7647 driver_name));
7651 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7652 * decide if the driver init data should be deleted. The rules are:
7653 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7654 * 2) delete init data only if there is no 2k/Xp driver
7655 * 3) always delete init data
7656 * The generalized rule is always use init data from the highest order driver.
7657 * It is necessary to follow the driver install by an initialization step to
7658 * finish off this process.
7660 if (level == 3)
7661 version = driver.info_3->cversion;
7662 else if (level == 6)
7663 version = driver.info_6->version;
7664 else
7665 version = -1;
7666 switch (version) {
7668 * 9x printer driver - never delete init data
7670 case 0:
7671 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7672 driver_name));
7673 break;
7676 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7677 * there is no 2k/Xp driver init data for this driver name.
7679 case 2:
7681 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7683 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7685 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7687 if (!del_driver_init(driver_name))
7688 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7689 } else {
7691 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7693 free_a_printer_driver(driver1,3);
7694 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7695 driver_name));
7698 break;
7701 * 2k or Xp printer driver - always delete init data
7703 case 3:
7704 if (!del_driver_init(driver_name))
7705 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7706 break;
7708 default:
7709 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7710 break;
7714 done:
7715 free_a_printer_driver(driver, level);
7716 return err;
7719 /********************************************************************
7720 * spoolss_addprinterdriverex
7721 ********************************************************************/
7723 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7725 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7726 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7729 * we only support the semantics of AddPrinterDriver()
7730 * i.e. only copy files that are newer than existing ones
7733 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7734 return WERR_ACCESS_DENIED;
7736 ZERO_STRUCT(q_u_local);
7737 ZERO_STRUCT(r_u_local);
7739 /* just pass the information off to _spoolss_addprinterdriver() */
7740 q_u_local.server_name_ptr = q_u->server_name_ptr;
7741 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7742 q_u_local.level = q_u->level;
7743 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7745 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7748 /****************************************************************************
7749 ****************************************************************************/
7751 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7753 init_unistr(&info->name, name);
7756 /****************************************************************************
7757 ****************************************************************************/
7759 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7761 pstring path;
7762 pstring long_archi;
7763 fstring servername;
7764 char *pservername;
7765 const char *short_archi;
7766 DRIVER_DIRECTORY_1 *info=NULL;
7767 WERROR result = WERR_OK;
7769 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7770 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7772 /* check for beginning double '\'s and that the server
7773 long enough */
7775 pservername = servername;
7776 if ( *pservername == '\\' && strlen(servername)>2 ) {
7777 pservername += 2;
7780 if ( !is_myname_or_ipaddr( pservername ) )
7781 return WERR_INVALID_PARAM;
7783 if (!(short_archi = get_short_archi(long_archi)))
7784 return WERR_INVALID_ENVIRONMENT;
7786 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7787 return WERR_NOMEM;
7789 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7791 DEBUG(4,("printer driver directory: [%s]\n", path));
7793 fill_driverdir_1(info, path);
7795 *needed += spoolss_size_driverdir_info_1(info);
7797 if (*needed > offered) {
7798 result = WERR_INSUFFICIENT_BUFFER;
7799 goto out;
7802 if (!rpcbuf_alloc_size(buffer, *needed)) {
7803 result = WERR_NOMEM;
7804 goto out;
7807 smb_io_driverdir_1("", buffer, info, 0);
7809 out:
7810 SAFE_FREE(info);
7812 return result;
7815 /****************************************************************************
7816 ****************************************************************************/
7818 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7820 UNISTR2 *name = &q_u->name;
7821 UNISTR2 *uni_environment = &q_u->environment;
7822 uint32 level = q_u->level;
7823 RPC_BUFFER *buffer = NULL;
7824 uint32 offered = q_u->offered;
7825 uint32 *needed = &r_u->needed;
7827 /* that's an [in out] buffer */
7829 if (!q_u->buffer && (offered!=0)) {
7830 return WERR_INVALID_PARAM;
7833 rpcbuf_move(q_u->buffer, &r_u->buffer);
7834 buffer = r_u->buffer;
7836 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7838 *needed=0;
7840 switch(level) {
7841 case 1:
7842 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7843 default:
7844 return WERR_UNKNOWN_LEVEL;
7848 /****************************************************************************
7849 ****************************************************************************/
7851 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7853 POLICY_HND *handle = &q_u->handle;
7854 uint32 idx = q_u->index;
7855 uint32 in_value_len = q_u->valuesize;
7856 uint32 in_data_len = q_u->datasize;
7857 uint32 *out_max_value_len = &r_u->valuesize;
7858 uint16 **out_value = &r_u->value;
7859 uint32 *out_value_len = &r_u->realvaluesize;
7860 uint32 *out_type = &r_u->type;
7861 uint32 *out_max_data_len = &r_u->datasize;
7862 uint8 **data_out = &r_u->data;
7863 uint32 *out_data_len = &r_u->realdatasize;
7865 NT_PRINTER_INFO_LEVEL *printer = NULL;
7867 uint32 biggest_valuesize;
7868 uint32 biggest_datasize;
7869 uint32 data_len;
7870 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7871 int snum;
7872 WERROR result;
7873 REGISTRY_VALUE *val = NULL;
7874 NT_PRINTER_DATA *p_data;
7875 int i, key_index, num_values;
7876 int name_length;
7878 *out_type = 0;
7880 *out_max_data_len = 0;
7881 *data_out = NULL;
7882 *out_data_len = 0;
7884 DEBUG(5,("spoolss_enumprinterdata\n"));
7886 if (!Printer) {
7887 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7888 return WERR_BADFID;
7891 if (!get_printer_snum(p,handle, &snum))
7892 return WERR_BADFID;
7894 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7895 if (!W_ERROR_IS_OK(result))
7896 return result;
7898 p_data = printer->info_2->data;
7899 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7901 result = WERR_OK;
7904 * The NT machine wants to know the biggest size of value and data
7906 * cf: MSDN EnumPrinterData remark section
7909 if ( !in_value_len && !in_data_len && (key_index != -1) )
7911 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7913 biggest_valuesize = 0;
7914 biggest_datasize = 0;
7916 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7918 for ( i=0; i<num_values; i++ )
7920 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7922 name_length = strlen(val->valuename);
7923 if ( strlen(val->valuename) > biggest_valuesize )
7924 biggest_valuesize = name_length;
7926 if ( val->size > biggest_datasize )
7927 biggest_datasize = val->size;
7929 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7930 biggest_datasize));
7933 /* the value is an UNICODE string but real_value_size is the length
7934 in bytes including the trailing 0 */
7936 *out_value_len = 2 * (1+biggest_valuesize);
7937 *out_data_len = biggest_datasize;
7939 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7941 goto done;
7945 * the value len is wrong in NT sp3
7946 * that's the number of bytes not the number of unicode chars
7949 if ( key_index != -1 )
7950 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7952 if ( !val )
7955 /* out_value should default to "" or else NT4 has
7956 problems unmarshalling the response */
7958 *out_max_value_len=(in_value_len/sizeof(uint16));
7960 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7962 result = WERR_NOMEM;
7963 goto done;
7966 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7968 /* the data is counted in bytes */
7970 *out_max_data_len = in_data_len;
7971 *out_data_len = in_data_len;
7973 /* only allocate when given a non-zero data_len */
7975 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7977 result = WERR_NOMEM;
7978 goto done;
7981 result = WERR_NO_MORE_ITEMS;
7983 else
7986 * the value is:
7987 * - counted in bytes in the request
7988 * - counted in UNICODE chars in the max reply
7989 * - counted in bytes in the real size
7991 * take a pause *before* coding not *during* coding
7994 /* name */
7995 *out_max_value_len=(in_value_len/sizeof(uint16));
7996 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7998 result = WERR_NOMEM;
7999 goto done;
8002 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8004 /* type */
8006 *out_type = regval_type( val );
8008 /* data - counted in bytes */
8010 *out_max_data_len = in_data_len;
8011 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8013 result = WERR_NOMEM;
8014 goto done;
8016 data_len = regval_size(val);
8017 if ( *data_out )
8018 memcpy( *data_out, regval_data_p(val), data_len );
8019 *out_data_len = data_len;
8022 done:
8023 free_a_printer(&printer, 2);
8024 return result;
8027 /****************************************************************************
8028 ****************************************************************************/
8030 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8032 POLICY_HND *handle = &q_u->handle;
8033 UNISTR2 *value = &q_u->value;
8034 uint32 type = q_u->type;
8035 uint8 *data = q_u->data;
8036 uint32 real_len = q_u->real_len;
8038 NT_PRINTER_INFO_LEVEL *printer = NULL;
8039 int snum=0;
8040 WERROR status = WERR_OK;
8041 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8042 fstring valuename;
8044 DEBUG(5,("spoolss_setprinterdata\n"));
8046 if (!Printer) {
8047 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8048 return WERR_BADFID;
8051 if ( Printer->printer_type == SPLHND_SERVER ) {
8052 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8053 return WERR_INVALID_PARAM;
8056 if (!get_printer_snum(p,handle, &snum))
8057 return WERR_BADFID;
8060 * Access check : NT returns "access denied" if you make a
8061 * SetPrinterData call without the necessary privildge.
8062 * we were originally returning OK if nothing changed
8063 * which made Win2k issue **a lot** of SetPrinterData
8064 * when connecting to a printer --jerry
8067 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8069 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8070 status = WERR_ACCESS_DENIED;
8071 goto done;
8074 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8075 if (!W_ERROR_IS_OK(status))
8076 return status;
8078 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8081 * When client side code sets a magic printer data key, detect it and save
8082 * the current printer data and the magic key's data (its the DEVMODE) for
8083 * future printer/driver initializations.
8085 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8087 /* Set devmode and printer initialization info */
8088 status = save_driver_init( printer, 2, data, real_len );
8090 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8092 else
8094 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8095 type, data, real_len );
8096 if ( W_ERROR_IS_OK(status) )
8097 status = mod_a_printer(printer, 2);
8100 done:
8101 free_a_printer(&printer, 2);
8103 return status;
8106 /****************************************************************************
8107 ****************************************************************************/
8109 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8111 POLICY_HND *handle = &q_u->handle;
8112 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8113 int snum;
8115 DEBUG(5,("_spoolss_resetprinter\n"));
8118 * All we do is to check to see if the handle and queue is valid.
8119 * This call really doesn't mean anything to us because we only
8120 * support RAW printing. --jerry
8123 if (!Printer) {
8124 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8125 return WERR_BADFID;
8128 if (!get_printer_snum(p,handle, &snum))
8129 return WERR_BADFID;
8132 /* blindly return success */
8133 return WERR_OK;
8137 /****************************************************************************
8138 ****************************************************************************/
8140 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8142 POLICY_HND *handle = &q_u->handle;
8143 UNISTR2 *value = &q_u->valuename;
8145 NT_PRINTER_INFO_LEVEL *printer = NULL;
8146 int snum=0;
8147 WERROR status = WERR_OK;
8148 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8149 pstring valuename;
8151 DEBUG(5,("spoolss_deleteprinterdata\n"));
8153 if (!Printer) {
8154 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8155 return WERR_BADFID;
8158 if (!get_printer_snum(p, handle, &snum))
8159 return WERR_BADFID;
8161 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8162 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8163 return WERR_ACCESS_DENIED;
8166 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8167 if (!W_ERROR_IS_OK(status))
8168 return status;
8170 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8172 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8174 if ( W_ERROR_IS_OK(status) )
8175 mod_a_printer( printer, 2 );
8177 free_a_printer(&printer, 2);
8179 return status;
8182 /****************************************************************************
8183 ****************************************************************************/
8185 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8187 POLICY_HND *handle = &q_u->handle;
8188 FORM *form = &q_u->form;
8189 nt_forms_struct tmpForm;
8190 int snum;
8191 WERROR status = WERR_OK;
8192 NT_PRINTER_INFO_LEVEL *printer = NULL;
8194 int count=0;
8195 nt_forms_struct *list=NULL;
8196 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8198 DEBUG(5,("spoolss_addform\n"));
8200 if (!Printer) {
8201 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8202 return WERR_BADFID;
8206 /* forms can be added on printer of on the print server handle */
8208 if ( Printer->printer_type == SPLHND_PRINTER )
8210 if (!get_printer_snum(p,handle, &snum))
8211 return WERR_BADFID;
8213 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8214 if (!W_ERROR_IS_OK(status))
8215 goto done;
8218 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8219 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8220 status = WERR_ACCESS_DENIED;
8221 goto done;
8224 /* can't add if builtin */
8226 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8227 status = WERR_ALREADY_EXISTS;
8228 goto done;
8231 count = get_ntforms(&list);
8233 if(!add_a_form(&list, form, &count)) {
8234 status = WERR_NOMEM;
8235 goto done;
8238 write_ntforms(&list, count);
8241 * ChangeID must always be set if this is a printer
8244 if ( Printer->printer_type == SPLHND_PRINTER )
8245 status = mod_a_printer(printer, 2);
8247 done:
8248 if ( printer )
8249 free_a_printer(&printer, 2);
8250 SAFE_FREE(list);
8252 return status;
8255 /****************************************************************************
8256 ****************************************************************************/
8258 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8260 POLICY_HND *handle = &q_u->handle;
8261 UNISTR2 *form_name = &q_u->name;
8262 nt_forms_struct tmpForm;
8263 int count=0;
8264 nt_forms_struct *list=NULL;
8265 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8266 int snum;
8267 WERROR status = WERR_OK;
8268 NT_PRINTER_INFO_LEVEL *printer = NULL;
8270 DEBUG(5,("spoolss_deleteform\n"));
8272 if (!Printer) {
8273 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8274 return WERR_BADFID;
8277 /* forms can be deleted on printer of on the print server handle */
8279 if ( Printer->printer_type == SPLHND_PRINTER )
8281 if (!get_printer_snum(p,handle, &snum))
8282 return WERR_BADFID;
8284 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8285 if (!W_ERROR_IS_OK(status))
8286 goto done;
8289 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8290 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8291 status = WERR_ACCESS_DENIED;
8292 goto done;
8295 /* can't delete if builtin */
8297 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8298 status = WERR_INVALID_PARAM;
8299 goto done;
8302 count = get_ntforms(&list);
8304 if ( !delete_a_form(&list, form_name, &count, &status ))
8305 goto done;
8308 * ChangeID must always be set if this is a printer
8311 if ( Printer->printer_type == SPLHND_PRINTER )
8312 status = mod_a_printer(printer, 2);
8314 done:
8315 if ( printer )
8316 free_a_printer(&printer, 2);
8317 SAFE_FREE(list);
8319 return status;
8322 /****************************************************************************
8323 ****************************************************************************/
8325 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8327 POLICY_HND *handle = &q_u->handle;
8328 FORM *form = &q_u->form;
8329 nt_forms_struct tmpForm;
8330 int snum;
8331 WERROR status = WERR_OK;
8332 NT_PRINTER_INFO_LEVEL *printer = NULL;
8334 int count=0;
8335 nt_forms_struct *list=NULL;
8336 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8338 DEBUG(5,("spoolss_setform\n"));
8340 if (!Printer) {
8341 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8342 return WERR_BADFID;
8345 /* forms can be modified on printer of on the print server handle */
8347 if ( Printer->printer_type == SPLHND_PRINTER )
8349 if (!get_printer_snum(p,handle, &snum))
8350 return WERR_BADFID;
8352 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8353 if (!W_ERROR_IS_OK(status))
8354 goto done;
8357 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8358 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8359 status = WERR_ACCESS_DENIED;
8360 goto done;
8363 /* can't set if builtin */
8364 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8365 status = WERR_INVALID_PARAM;
8366 goto done;
8369 count = get_ntforms(&list);
8370 update_a_form(&list, form, count);
8371 write_ntforms(&list, count);
8374 * ChangeID must always be set if this is a printer
8377 if ( Printer->printer_type == SPLHND_PRINTER )
8378 status = mod_a_printer(printer, 2);
8381 done:
8382 if ( printer )
8383 free_a_printer(&printer, 2);
8384 SAFE_FREE(list);
8386 return status;
8389 /****************************************************************************
8390 enumprintprocessors level 1.
8391 ****************************************************************************/
8393 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8395 PRINTPROCESSOR_1 *info_1=NULL;
8396 WERROR result = WERR_OK;
8398 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8399 return WERR_NOMEM;
8401 (*returned) = 0x1;
8403 init_unistr(&info_1->name, "winprint");
8405 *needed += spoolss_size_printprocessor_info_1(info_1);
8407 if (*needed > offered) {
8408 result = WERR_INSUFFICIENT_BUFFER;
8409 goto out;
8412 if (!rpcbuf_alloc_size(buffer, *needed)) {
8413 result = WERR_NOMEM;
8414 goto out;
8417 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8419 out:
8420 SAFE_FREE(info_1);
8422 if ( !W_ERROR_IS_OK(result) )
8423 *returned = 0;
8425 return result;
8428 /****************************************************************************
8429 ****************************************************************************/
8431 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8433 uint32 level = q_u->level;
8434 RPC_BUFFER *buffer = NULL;
8435 uint32 offered = q_u->offered;
8436 uint32 *needed = &r_u->needed;
8437 uint32 *returned = &r_u->returned;
8439 /* that's an [in out] buffer */
8441 if (!q_u->buffer && (offered!=0)) {
8442 return WERR_INVALID_PARAM;
8445 rpcbuf_move(q_u->buffer, &r_u->buffer);
8446 buffer = r_u->buffer;
8448 DEBUG(5,("spoolss_enumprintprocessors\n"));
8451 * Enumerate the print processors ...
8453 * Just reply with "winprint", to keep NT happy
8454 * and I can use my nice printer checker.
8457 *returned=0;
8458 *needed=0;
8460 switch (level) {
8461 case 1:
8462 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8463 default:
8464 return WERR_UNKNOWN_LEVEL;
8468 /****************************************************************************
8469 enumprintprocdatatypes level 1.
8470 ****************************************************************************/
8472 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8474 PRINTPROCDATATYPE_1 *info_1=NULL;
8475 WERROR result = WERR_NOMEM;
8477 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8478 return WERR_NOMEM;
8480 (*returned) = 0x1;
8482 init_unistr(&info_1->name, "RAW");
8484 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8486 if (*needed > offered) {
8487 result = WERR_INSUFFICIENT_BUFFER;
8488 goto out;
8491 if (!rpcbuf_alloc_size(buffer, *needed)) {
8492 result = WERR_NOMEM;
8493 goto out;
8496 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8498 out:
8499 SAFE_FREE(info_1);
8501 if ( !W_ERROR_IS_OK(result) )
8502 *returned = 0;
8504 return result;
8507 /****************************************************************************
8508 ****************************************************************************/
8510 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8512 uint32 level = q_u->level;
8513 RPC_BUFFER *buffer = NULL;
8514 uint32 offered = q_u->offered;
8515 uint32 *needed = &r_u->needed;
8516 uint32 *returned = &r_u->returned;
8518 /* that's an [in out] buffer */
8520 if (!q_u->buffer && (offered!=0)) {
8521 return WERR_INVALID_PARAM;
8524 rpcbuf_move(q_u->buffer, &r_u->buffer);
8525 buffer = r_u->buffer;
8527 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8529 *returned=0;
8530 *needed=0;
8532 switch (level) {
8533 case 1:
8534 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8535 default:
8536 return WERR_UNKNOWN_LEVEL;
8540 /****************************************************************************
8541 enumprintmonitors level 1.
8542 ****************************************************************************/
8544 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8546 PRINTMONITOR_1 *info_1;
8547 WERROR result = WERR_OK;
8548 int i;
8550 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8551 return WERR_NOMEM;
8553 *returned = 2;
8555 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8556 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8558 for ( i=0; i<*returned; i++ ) {
8559 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8562 if (*needed > offered) {
8563 result = WERR_INSUFFICIENT_BUFFER;
8564 goto out;
8567 if (!rpcbuf_alloc_size(buffer, *needed)) {
8568 result = WERR_NOMEM;
8569 goto out;
8572 for ( i=0; i<*returned; i++ ) {
8573 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8576 out:
8577 SAFE_FREE(info_1);
8579 if ( !W_ERROR_IS_OK(result) )
8580 *returned = 0;
8582 return result;
8585 /****************************************************************************
8586 enumprintmonitors level 2.
8587 ****************************************************************************/
8589 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8591 PRINTMONITOR_2 *info_2;
8592 WERROR result = WERR_OK;
8593 int i;
8595 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8596 return WERR_NOMEM;
8598 *returned = 2;
8600 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8601 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8602 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8604 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8605 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8606 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8608 for ( i=0; i<*returned; i++ ) {
8609 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8612 if (*needed > offered) {
8613 result = WERR_INSUFFICIENT_BUFFER;
8614 goto out;
8617 if (!rpcbuf_alloc_size(buffer, *needed)) {
8618 result = WERR_NOMEM;
8619 goto out;
8622 for ( i=0; i<*returned; i++ ) {
8623 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8626 out:
8627 SAFE_FREE(info_2);
8629 if ( !W_ERROR_IS_OK(result) )
8630 *returned = 0;
8632 return result;
8635 /****************************************************************************
8636 ****************************************************************************/
8638 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8640 uint32 level = q_u->level;
8641 RPC_BUFFER *buffer = NULL;
8642 uint32 offered = q_u->offered;
8643 uint32 *needed = &r_u->needed;
8644 uint32 *returned = &r_u->returned;
8646 /* that's an [in out] buffer */
8648 if (!q_u->buffer && (offered!=0)) {
8649 return WERR_INVALID_PARAM;
8652 rpcbuf_move(q_u->buffer, &r_u->buffer);
8653 buffer = r_u->buffer;
8655 DEBUG(5,("spoolss_enumprintmonitors\n"));
8658 * Enumerate the print monitors ...
8660 * Just reply with "Local Port", to keep NT happy
8661 * and I can use my nice printer checker.
8664 *returned=0;
8665 *needed=0;
8667 switch (level) {
8668 case 1:
8669 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8670 case 2:
8671 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8672 default:
8673 return WERR_UNKNOWN_LEVEL;
8677 /****************************************************************************
8678 ****************************************************************************/
8680 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8681 NT_PRINTER_INFO_LEVEL *ntprinter,
8682 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8683 uint32 *needed)
8685 int i=0;
8686 BOOL found=False;
8687 JOB_INFO_1 *info_1=NULL;
8688 WERROR result = WERR_OK;
8690 info_1=SMB_MALLOC_P(JOB_INFO_1);
8692 if (info_1 == NULL) {
8693 return WERR_NOMEM;
8696 for (i=0; i<count && found==False; i++) {
8697 if ((*queue)[i].job==(int)jobid)
8698 found=True;
8701 if (found==False) {
8702 SAFE_FREE(info_1);
8703 /* NT treats not found as bad param... yet another bad choice */
8704 return WERR_INVALID_PARAM;
8707 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8709 *needed += spoolss_size_job_info_1(info_1);
8711 if (*needed > offered) {
8712 result = WERR_INSUFFICIENT_BUFFER;
8713 goto out;
8716 if (!rpcbuf_alloc_size(buffer, *needed)) {
8717 result = WERR_NOMEM;
8718 goto out;
8721 smb_io_job_info_1("", buffer, info_1, 0);
8723 out:
8724 SAFE_FREE(info_1);
8726 return result;
8729 /****************************************************************************
8730 ****************************************************************************/
8732 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8733 NT_PRINTER_INFO_LEVEL *ntprinter,
8734 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8735 uint32 *needed)
8737 int i = 0;
8738 BOOL found = False;
8739 JOB_INFO_2 *info_2;
8740 WERROR result;
8741 DEVICEMODE *devmode = NULL;
8742 NT_DEVICEMODE *nt_devmode = NULL;
8744 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8745 return WERR_NOMEM;
8747 ZERO_STRUCTP(info_2);
8749 for ( i=0; i<count && found==False; i++ )
8751 if ((*queue)[i].job == (int)jobid)
8752 found = True;
8755 if ( !found ) {
8756 /* NT treats not found as bad param... yet another bad
8757 choice */
8758 result = WERR_INVALID_PARAM;
8759 goto done;
8763 * if the print job does not have a DEVMODE associated with it,
8764 * just use the one for the printer. A NULL devicemode is not
8765 * a failure condition
8768 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8769 devmode = construct_dev_mode(lp_const_servicename(snum));
8770 else {
8771 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8772 ZERO_STRUCTP( devmode );
8773 convert_nt_devicemode( devmode, nt_devmode );
8777 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8779 *needed += spoolss_size_job_info_2(info_2);
8781 if (*needed > offered) {
8782 result = WERR_INSUFFICIENT_BUFFER;
8783 goto done;
8786 if (!rpcbuf_alloc_size(buffer, *needed)) {
8787 result = WERR_NOMEM;
8788 goto done;
8791 smb_io_job_info_2("", buffer, info_2, 0);
8793 result = WERR_OK;
8795 done:
8796 /* Cleanup allocated memory */
8798 free_job_info_2(info_2); /* Also frees devmode */
8799 SAFE_FREE(info_2);
8801 return result;
8804 /****************************************************************************
8805 ****************************************************************************/
8807 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8809 POLICY_HND *handle = &q_u->handle;
8810 uint32 jobid = q_u->jobid;
8811 uint32 level = q_u->level;
8812 RPC_BUFFER *buffer = NULL;
8813 uint32 offered = q_u->offered;
8814 uint32 *needed = &r_u->needed;
8815 WERROR wstatus = WERR_OK;
8816 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8817 int snum;
8818 int count;
8819 print_queue_struct *queue = NULL;
8820 print_status_struct prt_status;
8822 /* that's an [in out] buffer */
8824 if (!q_u->buffer && (offered!=0)) {
8825 return WERR_INVALID_PARAM;
8828 rpcbuf_move(q_u->buffer, &r_u->buffer);
8829 buffer = r_u->buffer;
8831 DEBUG(5,("spoolss_getjob\n"));
8833 *needed = 0;
8835 if (!get_printer_snum(p, handle, &snum))
8836 return WERR_BADFID;
8838 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8839 if ( !W_ERROR_IS_OK(wstatus) )
8840 return wstatus;
8842 count = print_queue_status(snum, &queue, &prt_status);
8844 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8845 count, prt_status.status, prt_status.message));
8847 switch ( level ) {
8848 case 1:
8849 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8850 buffer, offered, needed);
8851 break;
8852 case 2:
8853 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8854 buffer, offered, needed);
8855 break;
8856 default:
8857 wstatus = WERR_UNKNOWN_LEVEL;
8858 break;
8861 SAFE_FREE(queue);
8862 free_a_printer( &ntprinter, 2 );
8864 return wstatus;
8867 /********************************************************************
8868 spoolss_getprinterdataex
8870 From MSDN documentation of GetPrinterDataEx: pass request
8871 to GetPrinterData if key is "PrinterDriverData".
8872 ********************************************************************/
8874 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8876 POLICY_HND *handle = &q_u->handle;
8877 uint32 in_size = q_u->size;
8878 uint32 *type = &r_u->type;
8879 uint32 *out_size = &r_u->size;
8880 uint8 **data = &r_u->data;
8881 uint32 *needed = &r_u->needed;
8882 fstring keyname, valuename;
8884 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8886 NT_PRINTER_INFO_LEVEL *printer = NULL;
8887 int snum = 0;
8888 WERROR status = WERR_OK;
8890 DEBUG(4,("_spoolss_getprinterdataex\n"));
8892 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8893 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8895 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8896 keyname, valuename));
8898 /* in case of problem, return some default values */
8900 *needed = 0;
8901 *type = 0;
8902 *out_size = in_size;
8904 if (!Printer) {
8905 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8906 status = WERR_BADFID;
8907 goto done;
8910 /* Is the handle to a printer or to the server? */
8912 if (Printer->printer_type == SPLHND_SERVER) {
8913 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8914 status = WERR_INVALID_PARAM;
8915 goto done;
8918 if ( !get_printer_snum(p,handle, &snum) )
8919 return WERR_BADFID;
8921 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8922 if ( !W_ERROR_IS_OK(status) )
8923 goto done;
8925 /* check to see if the keyname is valid */
8926 if ( !strlen(keyname) ) {
8927 status = WERR_INVALID_PARAM;
8928 goto done;
8931 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8932 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8933 free_a_printer( &printer, 2 );
8934 status = WERR_BADFILE;
8935 goto done;
8938 /* When given a new keyname, we should just create it */
8940 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8942 if (*needed > *out_size)
8943 status = WERR_MORE_DATA;
8945 done:
8946 if ( !W_ERROR_IS_OK(status) )
8948 DEBUG(5, ("error: allocating %d\n", *out_size));
8950 /* reply this param doesn't exist */
8952 if ( *out_size )
8954 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8955 status = WERR_NOMEM;
8956 goto done;
8959 else {
8960 *data = NULL;
8964 if ( printer )
8965 free_a_printer( &printer, 2 );
8967 return status;
8970 /********************************************************************
8971 * spoolss_setprinterdataex
8972 ********************************************************************/
8974 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8976 POLICY_HND *handle = &q_u->handle;
8977 uint32 type = q_u->type;
8978 uint8 *data = q_u->data;
8979 uint32 real_len = q_u->real_len;
8981 NT_PRINTER_INFO_LEVEL *printer = NULL;
8982 int snum = 0;
8983 WERROR status = WERR_OK;
8984 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8985 fstring valuename;
8986 fstring keyname;
8987 char *oid_string;
8989 DEBUG(4,("_spoolss_setprinterdataex\n"));
8991 /* From MSDN documentation of SetPrinterDataEx: pass request to
8992 SetPrinterData if key is "PrinterDriverData" */
8994 if (!Printer) {
8995 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8996 return WERR_BADFID;
8999 if ( Printer->printer_type == SPLHND_SERVER ) {
9000 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9001 return WERR_INVALID_PARAM;
9004 if ( !get_printer_snum(p,handle, &snum) )
9005 return WERR_BADFID;
9008 * Access check : NT returns "access denied" if you make a
9009 * SetPrinterData call without the necessary privildge.
9010 * we were originally returning OK if nothing changed
9011 * which made Win2k issue **a lot** of SetPrinterData
9012 * when connecting to a printer --jerry
9015 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9017 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9018 return WERR_ACCESS_DENIED;
9021 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9022 if (!W_ERROR_IS_OK(status))
9023 return status;
9025 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9026 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9028 /* check for OID in valuename */
9030 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9032 *oid_string = '\0';
9033 oid_string++;
9036 /* save the registry data */
9038 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9040 if ( W_ERROR_IS_OK(status) )
9042 /* save the OID if one was specified */
9043 if ( oid_string ) {
9044 fstrcat( keyname, "\\" );
9045 fstrcat( keyname, SPOOL_OID_KEY );
9048 * I'm not checking the status here on purpose. Don't know
9049 * if this is right, but I'm returning the status from the
9050 * previous set_printer_dataex() call. I have no idea if
9051 * this is right. --jerry
9054 set_printer_dataex( printer, keyname, valuename,
9055 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9058 status = mod_a_printer(printer, 2);
9061 free_a_printer(&printer, 2);
9063 return status;
9067 /********************************************************************
9068 * spoolss_deleteprinterdataex
9069 ********************************************************************/
9071 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9073 POLICY_HND *handle = &q_u->handle;
9074 UNISTR2 *value = &q_u->valuename;
9075 UNISTR2 *key = &q_u->keyname;
9077 NT_PRINTER_INFO_LEVEL *printer = NULL;
9078 int snum=0;
9079 WERROR status = WERR_OK;
9080 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9081 pstring valuename, keyname;
9083 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9085 if (!Printer) {
9086 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9087 return WERR_BADFID;
9090 if (!get_printer_snum(p, handle, &snum))
9091 return WERR_BADFID;
9093 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9094 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9095 return WERR_ACCESS_DENIED;
9098 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9099 if (!W_ERROR_IS_OK(status))
9100 return status;
9102 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9103 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9105 status = delete_printer_dataex( printer, keyname, valuename );
9107 if ( W_ERROR_IS_OK(status) )
9108 mod_a_printer( printer, 2 );
9110 free_a_printer(&printer, 2);
9112 return status;
9115 /********************************************************************
9116 * spoolss_enumprinterkey
9117 ********************************************************************/
9120 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9122 fstring key;
9123 fstring *keynames = NULL;
9124 uint16 *enumkeys = NULL;
9125 int num_keys;
9126 int printerkey_len;
9127 POLICY_HND *handle = &q_u->handle;
9128 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9129 NT_PRINTER_DATA *data;
9130 NT_PRINTER_INFO_LEVEL *printer = NULL;
9131 int snum = 0;
9132 WERROR status = WERR_BADFILE;
9135 DEBUG(4,("_spoolss_enumprinterkey\n"));
9137 if (!Printer) {
9138 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9139 return WERR_BADFID;
9142 if ( !get_printer_snum(p,handle, &snum) )
9143 return WERR_BADFID;
9145 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9146 if (!W_ERROR_IS_OK(status))
9147 return status;
9149 /* get the list of subkey names */
9151 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9152 data = printer->info_2->data;
9154 num_keys = get_printer_subkeys( data, key, &keynames );
9156 if ( num_keys == -1 ) {
9157 status = WERR_BADFILE;
9158 goto done;
9161 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9163 r_u->needed = printerkey_len*2;
9165 if ( q_u->size < r_u->needed ) {
9166 status = WERR_MORE_DATA;
9167 goto done;
9170 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9171 status = WERR_NOMEM;
9172 goto done;
9175 status = WERR_OK;
9177 if ( q_u->size < r_u->needed )
9178 status = WERR_MORE_DATA;
9180 done:
9181 free_a_printer( &printer, 2 );
9182 SAFE_FREE( keynames );
9184 return status;
9187 /********************************************************************
9188 * spoolss_deleteprinterkey
9189 ********************************************************************/
9191 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9193 POLICY_HND *handle = &q_u->handle;
9194 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9195 fstring key;
9196 NT_PRINTER_INFO_LEVEL *printer = NULL;
9197 int snum=0;
9198 WERROR status;
9200 DEBUG(5,("spoolss_deleteprinterkey\n"));
9202 if (!Printer) {
9203 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9204 return WERR_BADFID;
9207 /* if keyname == NULL, return error */
9209 if ( !q_u->keyname.buffer )
9210 return WERR_INVALID_PARAM;
9212 if (!get_printer_snum(p, handle, &snum))
9213 return WERR_BADFID;
9215 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9216 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9217 return WERR_ACCESS_DENIED;
9220 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9221 if (!W_ERROR_IS_OK(status))
9222 return status;
9224 /* delete the key and all subneys */
9226 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9228 status = delete_all_printer_data( printer->info_2, key );
9230 if ( W_ERROR_IS_OK(status) )
9231 status = mod_a_printer(printer, 2);
9233 free_a_printer( &printer, 2 );
9235 return status;
9239 /********************************************************************
9240 * spoolss_enumprinterdataex
9241 ********************************************************************/
9243 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9245 POLICY_HND *handle = &q_u->handle;
9246 uint32 in_size = q_u->size;
9247 uint32 num_entries,
9248 needed;
9249 NT_PRINTER_INFO_LEVEL *printer = NULL;
9250 PRINTER_ENUM_VALUES *enum_values = NULL;
9251 NT_PRINTER_DATA *p_data;
9252 fstring key;
9253 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9254 int snum;
9255 WERROR result;
9256 int key_index;
9257 int i;
9258 REGISTRY_VALUE *val;
9259 char *value_name;
9260 uint32 data_len;
9263 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9265 if (!Printer) {
9266 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9267 return WERR_BADFID;
9271 * first check for a keyname of NULL or "". Win2k seems to send
9272 * this a lot and we should send back WERR_INVALID_PARAM
9273 * no need to spend time looking up the printer in this case.
9274 * --jerry
9277 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9278 if ( !strlen(key) ) {
9279 result = WERR_INVALID_PARAM;
9280 goto done;
9283 /* get the printer off of disk */
9285 if (!get_printer_snum(p,handle, &snum))
9286 return WERR_BADFID;
9288 ZERO_STRUCT(printer);
9289 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9290 if (!W_ERROR_IS_OK(result))
9291 return result;
9293 /* now look for a match on the key name */
9295 p_data = printer->info_2->data;
9297 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9298 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9300 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9301 result = WERR_INVALID_PARAM;
9302 goto done;
9305 result = WERR_OK;
9306 needed = 0;
9308 /* allocate the memory for the array of pointers -- if necessary */
9310 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9311 if ( num_entries )
9313 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9315 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9316 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9317 result = WERR_NOMEM;
9318 goto done;
9321 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9325 * loop through all params and build the array to pass
9326 * back to the client
9329 for ( i=0; i<num_entries; i++ )
9331 /* lookup the registry value */
9333 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9334 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9336 /* copy the data */
9338 value_name = regval_name( val );
9339 init_unistr( &enum_values[i].valuename, value_name );
9340 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9341 enum_values[i].type = regval_type( val );
9343 data_len = regval_size( val );
9344 if ( data_len ) {
9345 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9347 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9348 data_len ));
9349 result = WERR_NOMEM;
9350 goto done;
9353 enum_values[i].data_len = data_len;
9355 /* keep track of the size of the array in bytes */
9357 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9360 /* housekeeping information in the reply */
9362 r_u->needed = needed;
9363 r_u->returned = num_entries;
9365 if (needed > in_size) {
9366 result = WERR_MORE_DATA;
9367 goto done;
9370 /* copy data into the reply */
9372 r_u->ctr.size = r_u->needed;
9373 r_u->ctr.size_of_array = r_u->returned;
9374 r_u->ctr.values = enum_values;
9378 done:
9379 if ( printer )
9380 free_a_printer(&printer, 2);
9382 return result;
9385 /****************************************************************************
9386 ****************************************************************************/
9388 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9390 init_unistr(&info->name, name);
9393 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9394 UNISTR2 *environment,
9395 RPC_BUFFER *buffer,
9396 uint32 offered,
9397 uint32 *needed)
9399 pstring path;
9400 pstring long_archi;
9401 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9402 WERROR result = WERR_OK;
9404 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9406 if (!get_short_archi(long_archi))
9407 return WERR_INVALID_ENVIRONMENT;
9409 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9410 return WERR_NOMEM;
9412 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9414 fill_printprocessordirectory_1(info, path);
9416 *needed += spoolss_size_printprocessordirectory_info_1(info);
9418 if (*needed > offered) {
9419 result = WERR_INSUFFICIENT_BUFFER;
9420 goto out;
9423 if (!rpcbuf_alloc_size(buffer, *needed)) {
9424 result = WERR_INSUFFICIENT_BUFFER;
9425 goto out;
9428 smb_io_printprocessordirectory_1("", buffer, info, 0);
9430 out:
9431 SAFE_FREE(info);
9433 return result;
9436 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9438 uint32 level = q_u->level;
9439 RPC_BUFFER *buffer = NULL;
9440 uint32 offered = q_u->offered;
9441 uint32 *needed = &r_u->needed;
9442 WERROR result;
9444 /* that's an [in out] buffer */
9446 if (!q_u->buffer && (offered!=0)) {
9447 return WERR_INVALID_PARAM;
9450 rpcbuf_move(q_u->buffer, &r_u->buffer);
9451 buffer = r_u->buffer;
9453 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9455 *needed=0;
9457 switch(level) {
9458 case 1:
9459 result = getprintprocessordirectory_level_1
9460 (&q_u->name, &q_u->environment, buffer, offered, needed);
9461 break;
9462 default:
9463 result = WERR_UNKNOWN_LEVEL;
9466 return result;
9469 /*******************************************************************
9470 Streams the monitor UI DLL name in UNICODE
9471 *******************************************************************/
9473 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9474 RPC_BUFFER *out, uint32 *needed )
9476 const char *dllname = "tcpmonui.dll";
9478 *needed = (strlen(dllname)+1) * 2;
9480 if ( rpcbuf_get_size(out) < *needed ) {
9481 return WERR_INSUFFICIENT_BUFFER;
9484 if ( !make_monitorui_buf( out, dllname ) ) {
9485 return WERR_NOMEM;
9488 return WERR_OK;
9491 /*******************************************************************
9492 Create a new TCP/IP port
9493 *******************************************************************/
9495 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9496 RPC_BUFFER *out, uint32 *needed )
9498 NT_PORT_DATA_1 port1;
9499 pstring device_uri;
9501 ZERO_STRUCT( port1 );
9503 /* convert to our internal port data structure */
9505 if ( !convert_port_data_1( &port1, in ) ) {
9506 return WERR_NOMEM;
9509 /* create the device URI and call the add_port_hook() */
9511 switch ( port1.protocol ) {
9512 case PORT_PROTOCOL_DIRECT:
9513 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9514 break;
9516 case PORT_PROTOCOL_LPR:
9517 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9518 break;
9520 default:
9521 return WERR_UNKNOWN_PORT;
9524 return add_port_hook( token, port1.name, device_uri );
9527 /*******************************************************************
9528 *******************************************************************/
9530 struct xcv_api_table xcvtcp_cmds[] = {
9531 { "MonitorUI", xcvtcp_monitorui },
9532 { "AddPort", xcvtcp_addport},
9533 { NULL, NULL }
9536 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9537 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9538 uint32 *needed )
9540 int i;
9542 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9544 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9545 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9546 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9549 return WERR_BADFUNC;
9552 /*******************************************************************
9553 *******************************************************************/
9554 #if 0 /* don't support management using the "Local Port" monitor */
9556 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9557 RPC_BUFFER *out, uint32 *needed )
9559 const char *dllname = "localui.dll";
9561 *needed = (strlen(dllname)+1) * 2;
9563 if ( rpcbuf_get_size(out) < *needed ) {
9564 return WERR_INSUFFICIENT_BUFFER;
9567 if ( !make_monitorui_buf( out, dllname )) {
9568 return WERR_NOMEM;
9571 return WERR_OK;
9574 /*******************************************************************
9575 *******************************************************************/
9577 struct xcv_api_table xcvlocal_cmds[] = {
9578 { "MonitorUI", xcvlocal_monitorui },
9579 { NULL, NULL }
9581 #else
9582 struct xcv_api_table xcvlocal_cmds[] = {
9583 { NULL, NULL }
9585 #endif
9589 /*******************************************************************
9590 *******************************************************************/
9592 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9593 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9594 uint32 *needed )
9596 int i;
9598 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9600 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9601 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9602 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9604 return WERR_BADFUNC;
9607 /*******************************************************************
9608 *******************************************************************/
9610 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9612 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9613 fstring command;
9615 if (!Printer) {
9616 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9617 return WERR_BADFID;
9620 /* Has to be a handle to the TCP/IP port monitor */
9622 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9623 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9624 return WERR_BADFID;
9627 /* requires administrative access to the server */
9629 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9630 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9631 return WERR_ACCESS_DENIED;
9634 /* Get the command name. There's numerous commands supported by the
9635 TCPMON interface. */
9637 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9638 q_u->dataname.uni_str_len*2, 0);
9640 /* Allocate the outgoing buffer */
9642 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9644 switch ( Printer->printer_type ) {
9645 case SPLHND_PORTMON_TCP:
9646 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9647 &q_u->indata, &r_u->outdata, &r_u->needed );
9648 case SPLHND_PORTMON_LOCAL:
9649 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9650 &q_u->indata, &r_u->outdata, &r_u->needed );
9653 return WERR_INVALID_PRINT_MONITOR;