r14178: Clarify code for Coverity #49. Ensure we know we
[Samba/nascimento.git] / source3 / rpc_server / srv_spoolss_nt.c
blobaf413b8b70f6eb7306cf8df4abdc02771d0e23a7
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_"
44 /* Table to map the driver version */
45 /* to OS */
46 static const char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
48 "", /* unused ? */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
56 return "";
57 return drv_ver_to_os[ver];
60 struct table_node {
61 const char *long_archi;
62 const char *short_archi;
63 int version;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
72 int snum;
73 uint32 counter;
74 } counter_printer_0;
76 static counter_printer_0 *counter_list;
78 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
90 /* API table for Xcv Monitor functions */
92 struct xcv_api_table {
93 const char *name;
94 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
101 switch (v) {
102 case LPQ_QUEUED:
103 return 0;
104 case LPQ_PAUSED:
105 return JOB_STATUS_PAUSED;
106 case LPQ_SPOOLING:
107 return JOB_STATUS_SPOOLING;
108 case LPQ_PRINTING:
109 return JOB_STATUS_PRINTING;
110 case LPQ_ERROR:
111 return JOB_STATUS_ERROR;
112 case LPQ_DELETING:
113 return JOB_STATUS_DELETING;
114 case LPQ_OFFLINE:
115 return JOB_STATUS_OFFLINE;
116 case LPQ_PAPEROUT:
117 return JOB_STATUS_PAPEROUT;
118 case LPQ_PRINTED:
119 return JOB_STATUS_PRINTED;
120 case LPQ_DELETED:
121 return JOB_STATUS_DELETED;
122 case LPQ_BLOCKED:
123 return JOB_STATUS_BLOCKED;
124 case LPQ_USER_INTERVENTION:
125 return JOB_STATUS_USER_INTERVENTION;
127 return 0;
130 static int nt_printq_status(int v)
132 switch (v) {
133 case LPQ_PAUSED:
134 return PRINTER_STATUS_PAUSED;
135 case LPQ_QUEUED:
136 case LPQ_SPOOLING:
137 case LPQ_PRINTING:
138 return 0;
140 return 0;
143 /****************************************************************************
144 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
145 ****************************************************************************/
147 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
149 if (*pp == NULL)
150 return;
152 SAFE_FREE((*pp)->ctr.type);
153 SAFE_FREE(*pp);
156 /***************************************************************************
157 Disconnect from the client
158 ****************************************************************************/
160 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
162 WERROR result;
165 * Tell the specific printing tdb we no longer want messages for this printer
166 * by deregistering our PID.
169 if (!print_notify_deregister_pid(snum))
170 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
172 /* weird if the test succeds !!! */
173 if (smb_connections==0) {
174 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
175 return;
178 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
180 if (!W_ERROR_IS_OK(result))
181 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
182 dos_errstr(result)));
184 /* if it's the last connection, deconnect the IPC$ share */
185 if (smb_connections==1) {
187 cli_shutdown( notify_cli_pipe->cli );
188 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
190 message_deregister(MSG_PRINTER_NOTIFY2);
192 /* Tell the connections db we're no longer interested in
193 * printer notify messages. */
195 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
198 smb_connections--;
201 /****************************************************************************
202 Functions to free a printer entry datastruct.
203 ****************************************************************************/
205 static void free_printer_entry(void *ptr)
207 Printer_entry *Printer = (Printer_entry *)ptr;
209 if (Printer->notify.client_connected==True) {
210 int snum = -1;
212 if ( Printer->printer_type == SPLHND_SERVER) {
213 snum = -1;
214 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
215 } else if (Printer->printer_type == SPLHND_PRINTER) {
216 snum = print_queue_snum(Printer->sharename);
217 if (snum != -1)
218 srv_spoolss_replycloseprinter(snum,
219 &Printer->notify.client_hnd);
223 Printer->notify.flags=0;
224 Printer->notify.options=0;
225 Printer->notify.localmachine[0]='\0';
226 Printer->notify.printerlocal=0;
227 free_spool_notify_option(&Printer->notify.option);
228 Printer->notify.option=NULL;
229 Printer->notify.client_connected=False;
231 free_nt_devicemode( &Printer->nt_devmode );
232 free_a_printer( &Printer->printer_info, 2 );
234 talloc_destroy( Printer->ctx );
236 /* Remove from the internal list. */
237 DLIST_REMOVE(printers_list, Printer);
239 SAFE_FREE(Printer);
242 /****************************************************************************
243 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
244 ****************************************************************************/
246 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
248 SPOOL_NOTIFY_OPTION *new_sp = NULL;
250 if (!sp)
251 return NULL;
253 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
254 if (!new_sp)
255 return NULL;
257 *new_sp = *sp;
259 if (sp->ctr.count) {
260 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
262 if (!new_sp->ctr.type) {
263 SAFE_FREE(new_sp);
264 return NULL;
268 return new_sp;
271 /****************************************************************************
272 find printer index by handle
273 ****************************************************************************/
275 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
277 Printer_entry *find_printer = NULL;
279 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
280 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
281 return NULL;
284 return find_printer;
287 /****************************************************************************
288 Close printer index by handle.
289 ****************************************************************************/
291 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
293 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
295 if (!Printer) {
296 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
297 return False;
300 close_policy_hnd(p, hnd);
302 return True;
305 /****************************************************************************
306 Delete a printer given a handle.
307 ****************************************************************************/
308 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
310 char *cmd = lp_deleteprinter_cmd();
311 pstring command;
312 int ret;
313 SE_PRIV se_printop = SE_PRINT_OPERATOR;
314 BOOL is_print_op = False;
316 /* can't fail if we don't try */
318 if ( !*cmd )
319 return WERR_OK;
321 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
323 if ( token )
324 is_print_op = user_has_privileges( token, &se_printop );
326 DEBUG(10,("Running [%s]\n", command));
328 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
330 if ( is_print_op )
331 become_root();
333 if ( (ret = smbrun(command, NULL)) == 0 ) {
334 /* Tell everyone we updated smb.conf. */
335 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
338 if ( is_print_op )
339 unbecome_root();
341 /********** END SePrintOperatorPrivlege BLOCK **********/
343 DEBUGADD(10,("returned [%d]\n", ret));
345 if (ret != 0)
346 return WERR_BADFID; /* What to return here? */
348 /* go ahead and re-read the services immediately */
349 reload_services( False );
351 if ( lp_servicenumber( sharename ) < 0 )
352 return WERR_ACCESS_DENIED;
354 return WERR_OK;
357 /****************************************************************************
358 Delete a printer given a handle.
359 ****************************************************************************/
361 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
363 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
365 if (!Printer) {
366 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
367 return WERR_BADFID;
371 * It turns out that Windows allows delete printer on a handle
372 * opened by an admin user, then used on a pipe handle created
373 * by an anonymous user..... but they're working on security.... riiight !
374 * JRA.
377 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
378 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
379 return WERR_ACCESS_DENIED;
382 /* this does not need a become root since the access check has been
383 done on the handle already */
385 if (del_a_printer( Printer->sharename ) != 0) {
386 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
387 return WERR_BADFID;
390 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
393 /****************************************************************************
394 Return the snum of a printer corresponding to an handle.
395 ****************************************************************************/
397 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
399 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
401 if (!Printer) {
402 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
403 return False;
406 switch (Printer->printer_type) {
407 case SPLHND_PRINTER:
408 DEBUG(4,("short name:%s\n", Printer->sharename));
409 *number = print_queue_snum(Printer->sharename);
410 return (*number != -1);
411 case SPLHND_SERVER:
412 return False;
413 default:
414 return False;
418 /****************************************************************************
419 Set printer handle type.
420 Check if it's \\server or \\server\printer
421 ****************************************************************************/
423 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
425 DEBUG(3,("Setting printer type=%s\n", handlename));
427 if ( strlen(handlename) < 3 ) {
428 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
429 return False;
432 /* it's a print server */
433 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
434 DEBUGADD(4,("Printer is a print server\n"));
435 Printer->printer_type = SPLHND_SERVER;
437 /* it's a printer (set_printer_hnd_name() will handle port monitors */
438 else {
439 DEBUGADD(4,("Printer is a printer\n"));
440 Printer->printer_type = SPLHND_PRINTER;
443 return True;
446 /****************************************************************************
447 Set printer handle name.. Accept names like \\server, \\server\printer,
448 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
449 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
450 XcvDataPort() interface.
451 ****************************************************************************/
453 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
455 int snum;
456 int n_services=lp_numservices();
457 char *aprinter, *printername;
458 const char *servername;
459 fstring sname;
460 BOOL found=False;
461 NT_PRINTER_INFO_LEVEL *printer;
462 WERROR result;
464 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
466 aprinter = handlename;
467 if ( *handlename == '\\' ) {
468 servername = handlename + 2;
469 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
470 *aprinter = '\0';
471 aprinter++;
474 else {
475 servername = "";
478 /* save the servername to fill in replies on this handle */
480 if ( !is_myname_or_ipaddr( servername ) )
481 return False;
483 fstrcpy( Printer->servername, servername );
485 if ( Printer->printer_type == SPLHND_SERVER )
486 return True;
488 if ( Printer->printer_type != SPLHND_PRINTER )
489 return False;
491 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
493 /* check for the Port Monitor Interface */
495 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
496 Printer->printer_type = SPLHND_PORTMON_TCP;
497 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
498 found = True;
500 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
501 Printer->printer_type = SPLHND_PORTMON_LOCAL;
502 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
503 found = True;
506 /* Search all sharenames first as this is easier than pulling
507 the printer_info_2 off of disk. Don't use find_service() since
508 that calls out to map_username() */
510 /* do another loop to look for printernames */
512 for (snum=0; !found && snum<n_services; snum++) {
514 /* no point going on if this is not a printer */
516 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
517 continue;
519 fstrcpy(sname, lp_servicename(snum));
520 if ( strequal( aprinter, sname ) ) {
521 found = True;
522 break;
525 /* no point looking up the printer object if
526 we aren't allowing printername != sharename */
528 if ( lp_force_printername(snum) )
529 continue;
531 fstrcpy(sname, lp_servicename(snum));
533 printer = NULL;
534 result = get_a_printer( NULL, &printer, 2, sname );
535 if ( !W_ERROR_IS_OK(result) ) {
536 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
537 sname, dos_errstr(result)));
538 continue;
541 /* printername is always returned as \\server\printername */
542 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
543 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
544 printer->info_2->printername));
545 free_a_printer( &printer, 2);
546 continue;
549 printername++;
551 if ( strequal(printername, aprinter) ) {
552 found = True;
553 break;
556 DEBUGADD(10, ("printername: %s\n", printername));
558 free_a_printer( &printer, 2);
561 if ( !found ) {
562 DEBUGADD(4,("Printer not found\n"));
563 return False;
566 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
568 fstrcpy(Printer->sharename, sname);
570 return True;
573 /****************************************************************************
574 Find first available printer slot. creates a printer handle for you.
575 ****************************************************************************/
577 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
579 Printer_entry *new_printer;
581 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
583 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
584 return False;
586 ZERO_STRUCTP(new_printer);
588 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
589 SAFE_FREE(new_printer);
590 return False;
593 /* Add to the internal list. */
594 DLIST_ADD(printers_list, new_printer);
596 new_printer->notify.option=NULL;
598 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
599 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
600 close_printer_handle(p, hnd);
601 return False;
604 if (!set_printer_hnd_printertype(new_printer, name)) {
605 close_printer_handle(p, hnd);
606 return False;
609 if (!set_printer_hnd_name(new_printer, name)) {
610 close_printer_handle(p, hnd);
611 return False;
614 new_printer->access_granted = access_granted;
616 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
618 return True;
621 /***************************************************************************
622 check to see if the client motify handle is monitoring the notification
623 given by (notify_type, notify_field).
624 **************************************************************************/
626 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
627 uint16 notify_field)
629 return True;
632 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
633 uint16 notify_field)
635 SPOOL_NOTIFY_OPTION *option = p->notify.option;
636 uint32 i, j;
639 * Flags should always be zero when the change notify
640 * is registered by the client's spooler. A user Win32 app
641 * might use the flags though instead of the NOTIFY_OPTION_INFO
642 * --jerry
645 if (!option) {
646 return False;
649 if (p->notify.flags)
650 return is_monitoring_event_flags(
651 p->notify.flags, notify_type, notify_field);
653 for (i = 0; i < option->count; i++) {
655 /* Check match for notify_type */
657 if (option->ctr.type[i].type != notify_type)
658 continue;
660 /* Check match for field */
662 for (j = 0; j < option->ctr.type[i].count; j++) {
663 if (option->ctr.type[i].fields[j] == notify_field) {
664 return True;
669 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
670 p->servername, p->sharename, notify_type, notify_field));
672 return False;
675 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677 static void notify_one_value(struct spoolss_notify_msg *msg,
678 SPOOL_NOTIFY_INFO_DATA *data,
679 TALLOC_CTX *mem_ctx)
681 data->notify_data.value[0] = msg->notify.value[0];
682 data->notify_data.value[1] = 0;
685 static void notify_string(struct spoolss_notify_msg *msg,
686 SPOOL_NOTIFY_INFO_DATA *data,
687 TALLOC_CTX *mem_ctx)
689 UNISTR2 unistr;
691 /* The length of the message includes the trailing \0 */
693 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
695 data->notify_data.data.length = msg->len * 2;
696 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
698 if (!data->notify_data.data.string) {
699 data->notify_data.data.length = 0;
700 return;
703 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
706 static void notify_system_time(struct spoolss_notify_msg *msg,
707 SPOOL_NOTIFY_INFO_DATA *data,
708 TALLOC_CTX *mem_ctx)
710 SYSTEMTIME systime;
711 prs_struct ps;
713 if (msg->len != sizeof(time_t)) {
714 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
715 msg->len));
716 return;
719 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
720 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
721 return;
724 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
725 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
726 return;
729 if (!spoolss_io_system_time("", &ps, 0, &systime))
730 return;
732 data->notify_data.data.length = prs_offset(&ps);
733 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
735 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
737 prs_mem_free(&ps);
740 struct notify2_message_table {
741 const char *name;
742 void (*fn)(struct spoolss_notify_msg *msg,
743 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
746 static struct notify2_message_table printer_notify_table[] = {
747 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
748 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
749 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
750 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
751 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
752 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
753 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
754 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
755 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
756 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
757 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
758 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
759 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
760 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
761 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
762 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
763 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
764 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
765 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 static struct notify2_message_table job_notify_table[] = {
769 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
770 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
771 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
772 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
773 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
774 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
775 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
776 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
777 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
778 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
779 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
780 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
781 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
782 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
783 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
784 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
785 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
786 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
787 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
788 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
789 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
790 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
791 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
792 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
796 /***********************************************************************
797 Allocate talloc context for container object
798 **********************************************************************/
800 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
802 if ( !ctr )
803 return;
805 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
807 return;
810 /***********************************************************************
811 release all allocated memory and zero out structure
812 **********************************************************************/
814 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
816 if ( !ctr )
817 return;
819 if ( ctr->ctx )
820 talloc_destroy(ctr->ctx);
822 ZERO_STRUCTP(ctr);
824 return;
827 /***********************************************************************
828 **********************************************************************/
830 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
832 if ( !ctr )
833 return NULL;
835 return ctr->ctx;
838 /***********************************************************************
839 **********************************************************************/
841 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
843 if ( !ctr || !ctr->msg_groups )
844 return NULL;
846 if ( idx >= ctr->num_groups )
847 return NULL;
849 return &ctr->msg_groups[idx];
853 /***********************************************************************
854 How many groups of change messages do we have ?
855 **********************************************************************/
857 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
859 if ( !ctr )
860 return 0;
862 return ctr->num_groups;
865 /***********************************************************************
866 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
867 **********************************************************************/
869 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
871 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
872 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
873 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
874 int i, new_slot;
876 if ( !ctr || !msg )
877 return 0;
879 /* loop over all groups looking for a matching printer name */
881 for ( i=0; i<ctr->num_groups; i++ ) {
882 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
883 break;
886 /* add a new group? */
888 if ( i == ctr->num_groups ) {
889 ctr->num_groups++;
891 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
892 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
893 return 0;
895 ctr->msg_groups = groups;
897 /* clear the new entry and set the printer name */
899 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
900 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903 /* add the change messages; 'i' is the correct index now regardless */
905 msg_grp = &ctr->msg_groups[i];
907 msg_grp->num_msgs++;
909 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
910 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
911 return 0;
913 msg_grp->msgs = msg_list;
915 new_slot = msg_grp->num_msgs-1;
916 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
918 /* need to allocate own copy of data */
920 if ( msg->len != 0 )
921 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
923 return ctr->num_groups;
926 /***********************************************************************
927 Send a change notication message on all handles which have a call
928 back registered
929 **********************************************************************/
931 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
933 Printer_entry *p;
934 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
935 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
936 SPOOLSS_NOTIFY_MSG *messages;
937 int sending_msg_count;
939 if ( !msg_group ) {
940 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
941 return;
944 messages = msg_group->msgs;
946 if ( !messages ) {
947 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
948 return;
951 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
953 /* loop over all printers */
955 for (p = printers_list; p; p = p->next) {
956 SPOOL_NOTIFY_INFO_DATA *data;
957 uint32 data_len = 0;
958 uint32 id;
959 int i;
961 /* Is there notification on this handle? */
963 if ( !p->notify.client_connected )
964 continue;
966 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
968 /* For this printer? Print servers always receive
969 notifications. */
971 if ( ( p->printer_type == SPLHND_PRINTER ) &&
972 ( !strequal(msg_group->printername, p->sharename) ) )
973 continue;
975 DEBUG(10,("Our printer\n"));
977 /* allocate the max entries possible */
979 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
980 ZERO_STRUCTP(data);
982 /* build the array of change notifications */
984 sending_msg_count = 0;
986 for ( i=0; i<msg_group->num_msgs; i++ ) {
987 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
989 /* Are we monitoring this event? */
991 if (!is_monitoring_event(p, msg->type, msg->field))
992 continue;
994 sending_msg_count++;
997 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
998 msg->type, msg->field, p->sharename));
1001 * if the is a printer notification handle and not a job notification
1002 * type, then set the id to 0. Other wise just use what was specified
1003 * in the message.
1005 * When registering change notification on a print server handle
1006 * we always need to send back the id (snum) matching the printer
1007 * for which the change took place. For change notify registered
1008 * on a printer handle, this does not matter and the id should be 0.
1010 * --jerry
1013 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1014 id = 0;
1015 else
1016 id = msg->id;
1019 /* Convert unix jobid to smb jobid */
1021 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1022 id = sysjob_to_jobid(msg->id);
1024 if (id == -1) {
1025 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1026 goto done;
1030 construct_info_data( &data[data_len], msg->type, msg->field, id );
1032 switch(msg->type) {
1033 case PRINTER_NOTIFY_TYPE:
1034 if ( printer_notify_table[msg->field].fn )
1035 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1036 break;
1038 case JOB_NOTIFY_TYPE:
1039 if ( job_notify_table[msg->field].fn )
1040 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1041 break;
1043 default:
1044 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1045 goto done;
1048 data_len++;
1051 if ( sending_msg_count ) {
1052 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1053 data_len, data, p->notify.change, 0 );
1057 done:
1058 DEBUG(8,("send_notify2_changes: Exit...\n"));
1059 return;
1062 /***********************************************************************
1063 **********************************************************************/
1065 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1068 uint32 tv_sec, tv_usec;
1069 size_t offset = 0;
1071 /* Unpack message */
1073 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1074 msg->printer);
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1077 &tv_sec, &tv_usec,
1078 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1080 if (msg->len == 0)
1081 tdb_unpack((char *)buf + offset, len - offset, "dd",
1082 &msg->notify.value[0], &msg->notify.value[1]);
1083 else
1084 tdb_unpack((char *)buf + offset, len - offset, "B",
1085 &msg->len, &msg->notify.data);
1087 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1088 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1090 tv->tv_sec = tv_sec;
1091 tv->tv_usec = tv_usec;
1093 if (msg->len == 0)
1094 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1095 msg->notify.value[1]));
1096 else
1097 dump_data(3, msg->notify.data, msg->len);
1099 return True;
1102 /********************************************************************
1103 Receive a notify2 message list
1104 ********************************************************************/
1106 static void receive_notify2_message_list(int msg_type, struct process_id src,
1107 void *msg, size_t len)
1109 size_t msg_count, i;
1110 char *buf = (char *)msg;
1111 char *msg_ptr;
1112 size_t msg_len;
1113 SPOOLSS_NOTIFY_MSG notify;
1114 SPOOLSS_NOTIFY_MSG_CTR messages;
1115 int num_groups;
1117 if (len < 4) {
1118 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1119 return;
1122 msg_count = IVAL(buf, 0);
1123 msg_ptr = buf + 4;
1125 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1127 if (msg_count == 0) {
1128 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1129 return;
1132 /* initialize the container */
1134 ZERO_STRUCT( messages );
1135 notify_msg_ctr_init( &messages );
1138 * build message groups for each printer identified
1139 * in a change_notify msg. Remember that a PCN message
1140 * includes the handle returned for the srv_spoolss_replyopenprinter()
1141 * call. Therefore messages are grouped according to printer handle.
1144 for ( i=0; i<msg_count; i++ ) {
1145 struct timeval msg_tv;
1147 if (msg_ptr + 4 - buf > len) {
1148 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1149 return;
1152 msg_len = IVAL(msg_ptr,0);
1153 msg_ptr += 4;
1155 if (msg_ptr + msg_len - buf > len) {
1156 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1157 return;
1160 /* unpack messages */
1162 ZERO_STRUCT( notify );
1163 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1164 msg_ptr += msg_len;
1166 /* add to correct list in container */
1168 notify_msg_ctr_addmsg( &messages, &notify );
1170 /* free memory that might have been allocated by notify2_unpack_msg() */
1172 if ( notify.len != 0 )
1173 SAFE_FREE( notify.notify.data );
1176 /* process each group of messages */
1178 num_groups = notify_msg_ctr_numgroups( &messages );
1179 for ( i=0; i<num_groups; i++ )
1180 send_notify2_changes( &messages, i );
1183 /* cleanup */
1185 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1187 notify_msg_ctr_destroy( &messages );
1189 return;
1192 /********************************************************************
1193 Send a message to ourself about new driver being installed
1194 so we can upgrade the information for each printer bound to this
1195 driver
1196 ********************************************************************/
1198 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1200 int len = strlen(drivername);
1202 if (!len)
1203 return False;
1205 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1206 drivername));
1208 message_send_pid(pid_to_procid(sys_getpid()),
1209 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1211 return True;
1214 /**********************************************************************
1215 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1216 over all printers, upgrading ones as necessary
1217 **********************************************************************/
1219 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1221 fstring drivername;
1222 int snum;
1223 int n_services = lp_numservices();
1225 len = MIN(len,sizeof(drivername)-1);
1226 strncpy(drivername, buf, len);
1228 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1230 /* Iterate the printer list */
1232 for (snum=0; snum<n_services; snum++)
1234 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1236 WERROR result;
1237 NT_PRINTER_INFO_LEVEL *printer = NULL;
1239 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1240 if (!W_ERROR_IS_OK(result))
1241 continue;
1243 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1245 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1247 /* all we care about currently is the change_id */
1249 result = mod_a_printer(printer, 2);
1250 if (!W_ERROR_IS_OK(result)) {
1251 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1252 dos_errstr(result)));
1256 free_a_printer(&printer, 2);
1260 /* all done */
1263 /********************************************************************
1264 Update the cache for all printq's with a registered client
1265 connection
1266 ********************************************************************/
1268 void update_monitored_printq_cache( void )
1270 Printer_entry *printer = printers_list;
1271 int snum;
1273 /* loop through all printers and update the cache where
1274 client_connected == True */
1275 while ( printer )
1277 if ( (printer->printer_type == SPLHND_PRINTER)
1278 && printer->notify.client_connected )
1280 snum = print_queue_snum(printer->sharename);
1281 print_queue_status( snum, NULL, NULL );
1284 printer = printer->next;
1287 return;
1289 /********************************************************************
1290 Send a message to ourself about new driver being installed
1291 so we can upgrade the information for each printer bound to this
1292 driver
1293 ********************************************************************/
1295 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1297 int len = strlen(drivername);
1299 if (!len)
1300 return False;
1302 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1303 drivername));
1305 message_send_pid(pid_to_procid(sys_getpid()),
1306 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1308 return True;
1311 /**********************************************************************
1312 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1313 over all printers, resetting printer data as neessary
1314 **********************************************************************/
1316 void reset_all_printerdata(int msg_type, struct process_id src,
1317 void *buf, size_t len)
1319 fstring drivername;
1320 int snum;
1321 int n_services = lp_numservices();
1323 len = MIN( len, sizeof(drivername)-1 );
1324 strncpy( drivername, buf, len );
1326 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1328 /* Iterate the printer list */
1330 for ( snum=0; snum<n_services; snum++ )
1332 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1334 WERROR result;
1335 NT_PRINTER_INFO_LEVEL *printer = NULL;
1337 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1338 if ( !W_ERROR_IS_OK(result) )
1339 continue;
1342 * if the printer is bound to the driver,
1343 * then reset to the new driver initdata
1346 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1348 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1350 if ( !set_driver_init(printer, 2) ) {
1351 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1352 printer->info_2->printername, printer->info_2->drivername));
1355 result = mod_a_printer( printer, 2 );
1356 if ( !W_ERROR_IS_OK(result) ) {
1357 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1358 get_dos_error_msg(result)));
1362 free_a_printer( &printer, 2 );
1366 /* all done */
1368 return;
1371 /********************************************************************
1372 Copy routines used by convert_to_openprinterex()
1373 *******************************************************************/
1375 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1377 DEVICEMODE *d;
1378 int len;
1380 if (!devmode)
1381 return NULL;
1383 DEBUG (8,("dup_devmode\n"));
1385 /* bulk copy first */
1387 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1388 if (!d)
1389 return NULL;
1391 /* dup the pointer members separately */
1393 len = unistrlen(devmode->devicename.buffer);
1394 if (len != -1) {
1395 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1396 if (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 (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1405 return NULL;
1408 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1410 return d;
1413 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1415 if (!new_ctr || !ctr)
1416 return;
1418 DEBUG(8,("copy_devmode_ctr\n"));
1420 new_ctr->size = ctr->size;
1421 new_ctr->devmode_ptr = ctr->devmode_ptr;
1423 if(ctr->devmode_ptr)
1424 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1427 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1429 if (!new_def || !def)
1430 return;
1432 DEBUG(8,("copy_printer_defaults\n"));
1434 new_def->datatype_ptr = def->datatype_ptr;
1436 if (def->datatype_ptr)
1437 copy_unistr2(&new_def->datatype, &def->datatype);
1439 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1441 new_def->access_required = def->access_required;
1444 /********************************************************************
1445 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1446 * SPOOL_Q_OPEN_PRINTER_EX structure
1447 ********************************************************************/
1449 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1451 if (!q_u_ex || !q_u)
1452 return WERR_OK;
1454 DEBUG(8,("convert_to_openprinterex\n"));
1456 if ( q_u->printername ) {
1457 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1458 if (q_u_ex->printername == NULL)
1459 return WERR_NOMEM;
1460 copy_unistr2(q_u_ex->printername, q_u->printername);
1463 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1465 return WERR_OK;
1468 /********************************************************************
1469 * spoolss_open_printer
1471 * called from the spoolss dispatcher
1472 ********************************************************************/
1474 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1476 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1477 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1479 if (!q_u || !r_u)
1480 return WERR_NOMEM;
1482 ZERO_STRUCT(q_u_ex);
1483 ZERO_STRUCT(r_u_ex);
1485 /* convert the OpenPrinter() call to OpenPrinterEx() */
1487 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1488 if (!W_ERROR_IS_OK(r_u_ex.status))
1489 return r_u_ex.status;
1491 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1493 /* convert back to OpenPrinter() */
1495 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1497 return r_u->status;
1500 /********************************************************************
1501 ********************************************************************/
1503 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1505 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1506 POLICY_HND *handle = &r_u->handle;
1508 fstring name;
1509 int snum;
1510 struct current_user user;
1511 Printer_entry *Printer=NULL;
1513 if ( !q_u->printername )
1514 return WERR_INVALID_PRINTER_NAME;
1516 /* some sanity check because you can open a printer or a print server */
1517 /* aka: \\server\printer or \\server */
1519 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1521 DEBUGADD(3,("checking name: %s\n",name));
1523 if (!open_printer_hnd(p, handle, name, 0))
1524 return WERR_INVALID_PRINTER_NAME;
1526 Printer=find_printer_index_by_hnd(p, handle);
1527 if ( !Printer ) {
1528 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1529 "handle we created for printer %s\n", name ));
1530 close_printer_handle(p,handle);
1531 return WERR_INVALID_PRINTER_NAME;
1534 get_current_user(&user, p);
1537 * First case: the user is opening the print server:
1539 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1540 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1542 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1543 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1544 * or if the user is listed in the smb.conf printer admin parameter.
1546 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1547 * client view printer folder, but does not show the MSAPW.
1549 * Note: this test needs code to check access rights here too. Jeremy
1550 * could you look at this?
1552 * Second case: the user is opening a printer:
1553 * NT doesn't let us connect to a printer if the connecting user
1554 * doesn't have print permission.
1556 * Third case: user is opening a Port Monitor
1557 * access checks same as opening a handle to the print server.
1560 switch (Printer->printer_type )
1562 case SPLHND_SERVER:
1563 case SPLHND_PORTMON_TCP:
1564 case SPLHND_PORTMON_LOCAL:
1565 /* Printserver handles use global struct... */
1567 snum = -1;
1569 /* Map standard access rights to object specific access rights */
1571 se_map_standard(&printer_default->access_required,
1572 &printserver_std_mapping);
1574 /* Deny any object specific bits that don't apply to print
1575 servers (i.e printer and job specific bits) */
1577 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1579 if (printer_default->access_required &
1580 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1581 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1582 close_printer_handle(p, handle);
1583 return WERR_ACCESS_DENIED;
1586 /* Allow admin access */
1588 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1590 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1592 if (!lp_ms_add_printer_wizard()) {
1593 close_printer_handle(p, handle);
1594 return WERR_ACCESS_DENIED;
1597 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1598 and not a printer admin, then fail */
1600 if ((user.ut.uid != 0) &&
1601 !user_has_privileges(user.nt_user_token,
1602 &se_printop ) &&
1603 !token_contains_name_in_list(
1604 uidtoname(user.ut.uid), NULL,
1605 user.nt_user_token,
1606 lp_printer_admin(snum))) {
1607 close_printer_handle(p, handle);
1608 return WERR_ACCESS_DENIED;
1611 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1613 else
1615 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1618 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1619 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1621 /* We fall through to return WERR_OK */
1622 break;
1624 case SPLHND_PRINTER:
1625 /* NT doesn't let us connect to a printer if the connecting user
1626 doesn't have print permission. */
1628 if (!get_printer_snum(p, handle, &snum)) {
1629 close_printer_handle(p, handle);
1630 return WERR_BADFID;
1633 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1635 /* map an empty access mask to the minimum access mask */
1636 if (printer_default->access_required == 0x0)
1637 printer_default->access_required = PRINTER_ACCESS_USE;
1640 * If we are not serving the printer driver for this printer,
1641 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1642 * will keep NT clients happy --jerry
1645 if (lp_use_client_driver(snum)
1646 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1648 printer_default->access_required = PRINTER_ACCESS_USE;
1651 /* check smb.conf parameters and the the sec_desc */
1653 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1654 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1655 return WERR_ACCESS_DENIED;
1658 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1659 snum) ||
1660 !print_access_check(&user, snum,
1661 printer_default->access_required)) {
1662 DEBUG(3, ("access DENIED for printer open\n"));
1663 close_printer_handle(p, handle);
1664 return WERR_ACCESS_DENIED;
1667 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1668 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1669 close_printer_handle(p, handle);
1670 return WERR_ACCESS_DENIED;
1673 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1674 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1675 else
1676 printer_default->access_required = PRINTER_ACCESS_USE;
1678 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1679 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1681 break;
1683 default:
1684 /* sanity check to prevent programmer error */
1685 return WERR_BADFID;
1688 Printer->access_granted = printer_default->access_required;
1691 * If the client sent a devmode in the OpenPrinter() call, then
1692 * save it here in case we get a job submission on this handle
1695 if ( (Printer->printer_type != SPLHND_SERVER)
1696 && q_u->printer_default.devmode_cont.devmode_ptr )
1698 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1699 &Printer->nt_devmode );
1702 #if 0 /* JERRY -- I'm doubtful this is really effective */
1703 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1704 optimization in Windows 2000 clients --jerry */
1706 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1707 && (RA_WIN2K == get_remote_arch()) )
1709 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1710 sys_usleep( 500000 );
1712 #endif
1714 return WERR_OK;
1717 /****************************************************************************
1718 ****************************************************************************/
1720 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1721 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1723 BOOL ret;
1725 switch (level) {
1726 case 2:
1727 /* allocate memory if needed. Messy because
1728 convert_printer_info is used to update an existing
1729 printer or build a new one */
1731 if ( !printer->info_2 ) {
1732 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1733 if ( !printer->info_2 ) {
1734 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1735 return False;
1739 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1740 printer->info_2->setuptime = time(NULL);
1742 return ret;
1745 return False;
1748 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1749 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1751 BOOL result = True;
1753 switch (level) {
1754 case 3:
1755 printer->info_3=NULL;
1756 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1757 result = False;
1758 break;
1759 case 6:
1760 printer->info_6=NULL;
1761 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1762 result = False;
1763 break;
1764 default:
1765 break;
1768 return result;
1771 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1772 NT_DEVICEMODE **pp_nt_devmode)
1774 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1777 * Ensure nt_devmode is a valid pointer
1778 * as we will be overwriting it.
1781 if (nt_devmode == NULL) {
1782 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1783 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1784 return False;
1787 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1788 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1790 nt_devmode->specversion=devmode->specversion;
1791 nt_devmode->driverversion=devmode->driverversion;
1792 nt_devmode->size=devmode->size;
1793 nt_devmode->fields=devmode->fields;
1794 nt_devmode->orientation=devmode->orientation;
1795 nt_devmode->papersize=devmode->papersize;
1796 nt_devmode->paperlength=devmode->paperlength;
1797 nt_devmode->paperwidth=devmode->paperwidth;
1798 nt_devmode->scale=devmode->scale;
1799 nt_devmode->copies=devmode->copies;
1800 nt_devmode->defaultsource=devmode->defaultsource;
1801 nt_devmode->printquality=devmode->printquality;
1802 nt_devmode->color=devmode->color;
1803 nt_devmode->duplex=devmode->duplex;
1804 nt_devmode->yresolution=devmode->yresolution;
1805 nt_devmode->ttoption=devmode->ttoption;
1806 nt_devmode->collate=devmode->collate;
1808 nt_devmode->logpixels=devmode->logpixels;
1809 nt_devmode->bitsperpel=devmode->bitsperpel;
1810 nt_devmode->pelswidth=devmode->pelswidth;
1811 nt_devmode->pelsheight=devmode->pelsheight;
1812 nt_devmode->displayflags=devmode->displayflags;
1813 nt_devmode->displayfrequency=devmode->displayfrequency;
1814 nt_devmode->icmmethod=devmode->icmmethod;
1815 nt_devmode->icmintent=devmode->icmintent;
1816 nt_devmode->mediatype=devmode->mediatype;
1817 nt_devmode->dithertype=devmode->dithertype;
1818 nt_devmode->reserved1=devmode->reserved1;
1819 nt_devmode->reserved2=devmode->reserved2;
1820 nt_devmode->panningwidth=devmode->panningwidth;
1821 nt_devmode->panningheight=devmode->panningheight;
1824 * Only change private and driverextra if the incoming devmode
1825 * has a new one. JRA.
1828 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1829 SAFE_FREE(nt_devmode->nt_dev_private);
1830 nt_devmode->driverextra=devmode->driverextra;
1831 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1832 return False;
1833 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1836 *pp_nt_devmode = nt_devmode;
1838 return True;
1841 /********************************************************************
1842 * _spoolss_enddocprinter_internal.
1843 ********************************************************************/
1845 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1847 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1848 int snum;
1850 if (!Printer) {
1851 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1852 return WERR_BADFID;
1855 if (!get_printer_snum(p, handle, &snum))
1856 return WERR_BADFID;
1858 Printer->document_started=False;
1859 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1860 /* error codes unhandled so far ... */
1862 return WERR_OK;
1865 /********************************************************************
1866 * api_spoolss_closeprinter
1867 ********************************************************************/
1869 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1871 POLICY_HND *handle = &q_u->handle;
1873 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1875 if (Printer && Printer->document_started)
1876 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1878 if (!close_printer_handle(p, handle))
1879 return WERR_BADFID;
1881 /* clear the returned printer handle. Observed behavior
1882 from Win2k server. Don't think this really matters.
1883 Previous code just copied the value of the closed
1884 handle. --jerry */
1886 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1888 return WERR_OK;
1891 /********************************************************************
1892 * api_spoolss_deleteprinter
1894 ********************************************************************/
1896 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1898 POLICY_HND *handle = &q_u->handle;
1899 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1900 WERROR result;
1902 if (Printer && Printer->document_started)
1903 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1905 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1907 result = delete_printer_handle(p, handle);
1909 update_c_setprinter(False);
1911 return result;
1914 /*******************************************************************
1915 * static function to lookup the version id corresponding to an
1916 * long architecture string
1917 ******************************************************************/
1919 static int get_version_id (char * arch)
1921 int i;
1922 struct table_node archi_table[]= {
1924 {"Windows 4.0", "WIN40", 0 },
1925 {"Windows NT x86", "W32X86", 2 },
1926 {"Windows NT R4000", "W32MIPS", 2 },
1927 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1928 {"Windows NT PowerPC", "W32PPC", 2 },
1929 {"Windows IA64", "IA64", 3 },
1930 {"Windows x64", "x64", 3 },
1931 {NULL, "", -1 }
1934 for (i=0; archi_table[i].long_archi != NULL; i++)
1936 if (strcmp(arch, archi_table[i].long_archi) == 0)
1937 return (archi_table[i].version);
1940 return -1;
1943 /********************************************************************
1944 * _spoolss_deleteprinterdriver
1945 ********************************************************************/
1947 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1949 fstring driver;
1950 fstring arch;
1951 NT_PRINTER_DRIVER_INFO_LEVEL info;
1952 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1953 int version;
1954 struct current_user user;
1955 WERROR status;
1956 WERROR status_win2k = WERR_ACCESS_DENIED;
1957 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1959 get_current_user(&user, p);
1961 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1962 and not a printer admin, then fail */
1964 if ( (user.ut.uid != 0)
1965 && !user_has_privileges(user.nt_user_token, &se_printop )
1966 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1967 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1969 return WERR_ACCESS_DENIED;
1972 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1973 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1975 /* check that we have a valid driver name first */
1977 if ((version=get_version_id(arch)) == -1)
1978 return WERR_INVALID_ENVIRONMENT;
1980 ZERO_STRUCT(info);
1981 ZERO_STRUCT(info_win2k);
1983 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1985 /* try for Win2k driver if "Windows NT x86" */
1987 if ( version == 2 ) {
1988 version = 3;
1989 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1990 status = WERR_UNKNOWN_PRINTER_DRIVER;
1991 goto done;
1994 /* otherwise it was a failure */
1995 else {
1996 status = WERR_UNKNOWN_PRINTER_DRIVER;
1997 goto done;
2002 if (printer_driver_in_use(info.info_3)) {
2003 status = WERR_PRINTER_DRIVER_IN_USE;
2004 goto done;
2007 if ( version == 2 )
2009 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2011 /* if we get to here, we now have 2 driver info structures to remove */
2012 /* remove the Win2k driver first*/
2014 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2015 free_a_printer_driver( info_win2k, 3 );
2017 /* this should not have failed---if it did, report to client */
2018 if ( !W_ERROR_IS_OK(status_win2k) )
2020 status = status_win2k;
2021 goto done;
2026 status = delete_printer_driver(info.info_3, &user, version, False);
2028 /* if at least one of the deletes succeeded return OK */
2030 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2031 status = WERR_OK;
2033 done:
2034 free_a_printer_driver( info, 3 );
2036 return status;
2039 /********************************************************************
2040 * spoolss_deleteprinterdriverex
2041 ********************************************************************/
2043 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2045 fstring driver;
2046 fstring arch;
2047 NT_PRINTER_DRIVER_INFO_LEVEL info;
2048 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2049 int version;
2050 uint32 flags = q_u->delete_flags;
2051 BOOL delete_files;
2052 struct current_user user;
2053 WERROR status;
2054 WERROR status_win2k = WERR_ACCESS_DENIED;
2055 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2057 get_current_user(&user, p);
2059 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2060 and not a printer admin, then fail */
2062 if ( (user.ut.uid != 0)
2063 && !user_has_privileges(user.nt_user_token, &se_printop )
2064 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2065 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2067 return WERR_ACCESS_DENIED;
2070 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2071 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2073 /* check that we have a valid driver name first */
2074 if ((version=get_version_id(arch)) == -1) {
2075 /* this is what NT returns */
2076 return WERR_INVALID_ENVIRONMENT;
2079 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2080 version = q_u->version;
2082 ZERO_STRUCT(info);
2083 ZERO_STRUCT(info_win2k);
2085 status = get_a_printer_driver(&info, 3, driver, arch, version);
2087 if ( !W_ERROR_IS_OK(status) )
2090 * if the client asked for a specific version,
2091 * or this is something other than Windows NT x86,
2092 * then we've failed
2095 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2096 goto done;
2098 /* try for Win2k driver if "Windows NT x86" */
2100 version = 3;
2101 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2102 status = WERR_UNKNOWN_PRINTER_DRIVER;
2103 goto done;
2107 if ( printer_driver_in_use(info.info_3) ) {
2108 status = WERR_PRINTER_DRIVER_IN_USE;
2109 goto done;
2113 * we have a couple of cases to consider.
2114 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2115 * then the delete should fail if **any** files overlap with
2116 * other drivers
2117 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2118 * non-overlapping files
2119 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2120 * is set, the do not delete any files
2121 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2124 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2126 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2128 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2129 /* no idea of the correct error here */
2130 status = WERR_ACCESS_DENIED;
2131 goto done;
2135 /* also check for W32X86/3 if necessary; maybe we already have? */
2137 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2138 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2141 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2142 /* no idea of the correct error here */
2143 free_a_printer_driver( info_win2k, 3 );
2144 status = WERR_ACCESS_DENIED;
2145 goto done;
2148 /* if we get to here, we now have 2 driver info structures to remove */
2149 /* remove the Win2k driver first*/
2151 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2152 free_a_printer_driver( info_win2k, 3 );
2154 /* this should not have failed---if it did, report to client */
2156 if ( !W_ERROR_IS_OK(status_win2k) )
2157 goto done;
2161 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2163 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2164 status = WERR_OK;
2165 done:
2166 free_a_printer_driver( info, 3 );
2168 return status;
2172 /****************************************************************************
2173 Internal routine for retreiving printerdata
2174 ***************************************************************************/
2176 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2177 const char *key, const char *value, uint32 *type, uint8 **data,
2178 uint32 *needed, uint32 in_size )
2180 REGISTRY_VALUE *val;
2181 uint32 size;
2182 int data_len;
2184 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2185 return WERR_BADFILE;
2187 *type = regval_type( val );
2189 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2191 size = regval_size( val );
2193 /* copy the min(in_size, len) */
2195 if ( in_size ) {
2196 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2198 /* special case for 0 length values */
2199 if ( data_len ) {
2200 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2201 return WERR_NOMEM;
2203 else {
2204 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2205 return WERR_NOMEM;
2208 else
2209 *data = NULL;
2211 *needed = size;
2213 DEBUG(5,("get_printer_dataex: copy done\n"));
2215 return WERR_OK;
2218 /****************************************************************************
2219 Internal routine for removing printerdata
2220 ***************************************************************************/
2222 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2224 return delete_printer_data( printer->info_2, key, value );
2227 /****************************************************************************
2228 Internal routine for storing printerdata
2229 ***************************************************************************/
2231 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2232 uint32 type, uint8 *data, int real_len )
2234 /* the registry objects enforce uniqueness based on value name */
2236 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2239 /********************************************************************
2240 GetPrinterData on a printer server Handle.
2241 ********************************************************************/
2243 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2245 int i;
2247 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2249 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2250 *type = REG_DWORD;
2251 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2252 return WERR_NOMEM;
2253 *needed = 0x4;
2254 return WERR_OK;
2257 if (!StrCaseCmp(value, "BeepEnabled")) {
2258 *type = REG_DWORD;
2259 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2260 return WERR_NOMEM;
2261 SIVAL(*data, 0, 0x00);
2262 *needed = 0x4;
2263 return WERR_OK;
2266 if (!StrCaseCmp(value, "EventLog")) {
2267 *type = REG_DWORD;
2268 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2269 return WERR_NOMEM;
2270 /* formally was 0x1b */
2271 SIVAL(*data, 0, 0x0);
2272 *needed = 0x4;
2273 return WERR_OK;
2276 if (!StrCaseCmp(value, "NetPopup")) {
2277 *type = REG_DWORD;
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2279 return WERR_NOMEM;
2280 SIVAL(*data, 0, 0x00);
2281 *needed = 0x4;
2282 return WERR_OK;
2285 if (!StrCaseCmp(value, "MajorVersion")) {
2286 *type = REG_DWORD;
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2288 return WERR_NOMEM;
2290 /* Windows NT 4.0 seems to not allow uploading of drivers
2291 to a server that reports 0x3 as the MajorVersion.
2292 need to investigate more how Win2k gets around this .
2293 -- jerry */
2295 if ( RA_WINNT == get_remote_arch() )
2296 SIVAL(*data, 0, 2);
2297 else
2298 SIVAL(*data, 0, 3);
2300 *needed = 0x4;
2301 return WERR_OK;
2304 if (!StrCaseCmp(value, "MinorVersion")) {
2305 *type = REG_DWORD;
2306 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2307 return WERR_NOMEM;
2308 SIVAL(*data, 0, 0);
2309 *needed = 0x4;
2310 return WERR_OK;
2313 /* REG_BINARY
2314 * uint32 size = 0x114
2315 * uint32 major = 5
2316 * uint32 minor = [0|1]
2317 * uint32 build = [2195|2600]
2318 * extra unicode string = e.g. "Service Pack 3"
2320 if (!StrCaseCmp(value, "OSVersion")) {
2321 *type = REG_BINARY;
2322 *needed = 0x114;
2324 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2325 return WERR_NOMEM;
2327 SIVAL(*data, 0, *needed); /* size */
2328 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2329 SIVAL(*data, 8, 0);
2330 SIVAL(*data, 12, 2195); /* build */
2332 /* leave extra string empty */
2334 return WERR_OK;
2338 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2339 const char *string="C:\\PRINTERS";
2340 *type = REG_SZ;
2341 *needed = 2*(strlen(string)+1);
2342 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2343 return WERR_NOMEM;
2344 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2346 /* it's done by hand ready to go on the wire */
2347 for (i=0; i<strlen(string); i++) {
2348 (*data)[2*i]=string[i];
2349 (*data)[2*i+1]='\0';
2351 return WERR_OK;
2354 if (!StrCaseCmp(value, "Architecture")) {
2355 const char *string="Windows NT x86";
2356 *type = REG_SZ;
2357 *needed = 2*(strlen(string)+1);
2358 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2359 return WERR_NOMEM;
2360 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2361 for (i=0; i<strlen(string); i++) {
2362 (*data)[2*i]=string[i];
2363 (*data)[2*i+1]='\0';
2365 return WERR_OK;
2368 if (!StrCaseCmp(value, "DsPresent")) {
2369 *type = REG_DWORD;
2370 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2371 return WERR_NOMEM;
2373 /* only show the publish check box if we are a
2374 memeber of a AD domain */
2376 if ( lp_security() == SEC_ADS )
2377 SIVAL(*data, 0, 0x01);
2378 else
2379 SIVAL(*data, 0, 0x00);
2381 *needed = 0x4;
2382 return WERR_OK;
2385 if (!StrCaseCmp(value, "DNSMachineName")) {
2386 pstring hostname;
2388 if (!get_mydnsfullname(hostname))
2389 return WERR_BADFILE;
2390 *type = REG_SZ;
2391 *needed = 2*(strlen(hostname)+1);
2392 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2393 return WERR_NOMEM;
2394 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2395 for (i=0; i<strlen(hostname); i++) {
2396 (*data)[2*i]=hostname[i];
2397 (*data)[2*i+1]='\0';
2399 return WERR_OK;
2403 return WERR_BADFILE;
2406 /********************************************************************
2407 * spoolss_getprinterdata
2408 ********************************************************************/
2410 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2412 POLICY_HND *handle = &q_u->handle;
2413 UNISTR2 *valuename = &q_u->valuename;
2414 uint32 in_size = q_u->size;
2415 uint32 *type = &r_u->type;
2416 uint32 *out_size = &r_u->size;
2417 uint8 **data = &r_u->data;
2418 uint32 *needed = &r_u->needed;
2419 WERROR status;
2420 fstring value;
2421 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2422 NT_PRINTER_INFO_LEVEL *printer = NULL;
2423 int snum = 0;
2426 * Reminder: when it's a string, the length is in BYTES
2427 * even if UNICODE is negociated.
2429 * JFM, 4/19/1999
2432 *out_size = in_size;
2434 /* in case of problem, return some default values */
2436 *needed = 0;
2437 *type = 0;
2439 DEBUG(4,("_spoolss_getprinterdata\n"));
2441 if ( !Printer ) {
2442 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2443 status = WERR_BADFID;
2444 goto done;
2447 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2449 if ( Printer->printer_type == SPLHND_SERVER )
2450 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2451 else
2453 if ( !get_printer_snum(p,handle, &snum) ) {
2454 status = WERR_BADFID;
2455 goto done;
2458 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2459 if ( !W_ERROR_IS_OK(status) )
2460 goto done;
2462 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2464 if ( strequal(value, "ChangeId") ) {
2465 *type = REG_DWORD;
2466 *needed = sizeof(uint32);
2467 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2468 status = WERR_NOMEM;
2469 goto done;
2471 SIVAL( *data, 0, printer->info_2->changeid );
2472 status = WERR_OK;
2474 else
2475 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2478 if (*needed > *out_size)
2479 status = WERR_MORE_DATA;
2481 done:
2482 if ( !W_ERROR_IS_OK(status) )
2484 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2486 /* reply this param doesn't exist */
2488 if ( *out_size ) {
2489 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2490 if ( printer )
2491 free_a_printer( &printer, 2 );
2492 return WERR_NOMEM;
2495 else {
2496 *data = NULL;
2500 /* cleanup & exit */
2502 if ( printer )
2503 free_a_printer( &printer, 2 );
2505 return status;
2508 /*********************************************************
2509 Connect to the client machine.
2510 **********************************************************/
2512 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2513 struct in_addr *client_ip, const char *remote_machine)
2515 NTSTATUS ret;
2516 struct cli_state *the_cli;
2517 struct in_addr rm_addr;
2519 if ( is_zero_ip(*client_ip) ) {
2520 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2521 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2522 return False;
2525 if ( ismyip( rm_addr )) {
2526 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2527 return False;
2529 } else {
2530 rm_addr.s_addr = client_ip->s_addr;
2531 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2532 inet_ntoa(*client_ip) ));
2535 /* setup the connection */
2537 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2538 &rm_addr, 0, "IPC$", "IPC",
2539 "", /* username */
2540 "", /* domain */
2541 "", /* password */
2542 0, lp_client_signing(), NULL );
2544 if ( !NT_STATUS_IS_OK( ret ) ) {
2545 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2546 remote_machine ));
2547 return False;
2550 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2551 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2552 cli_shutdown(the_cli);
2553 return False;
2557 * Ok - we have an anonymous connection to the IPC$ share.
2558 * Now start the NT Domain stuff :-).
2561 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2562 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2563 remote_machine, nt_errstr(ret)));
2564 cli_shutdown(the_cli);
2565 return False;
2568 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2570 (*pp_pipe)->cli = the_cli;
2572 return True;
2575 /***************************************************************************
2576 Connect to the client.
2577 ****************************************************************************/
2579 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2580 uint32 localprinter, uint32 type,
2581 POLICY_HND *handle, struct in_addr *client_ip)
2583 WERROR result;
2586 * If it's the first connection, contact the client
2587 * and connect to the IPC$ share anonymously
2589 if (smb_connections==0) {
2590 fstring unix_printer;
2592 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2594 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
2595 return False;
2597 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2598 /* Tell the connections db we're now interested in printer
2599 * notify messages. */
2600 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2604 * Tell the specific printing tdb we want messages for this printer
2605 * by registering our PID.
2608 if (!print_notify_register_pid(snum))
2609 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2611 smb_connections++;
2613 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2614 type, handle);
2616 if (!W_ERROR_IS_OK(result))
2617 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2618 dos_errstr(result)));
2620 return (W_ERROR_IS_OK(result));
2623 /********************************************************************
2624 * _spoolss_rffpcnex
2625 * ReplyFindFirstPrinterChangeNotifyEx
2627 * before replying OK: status=0 a rpc call is made to the workstation
2628 * asking ReplyOpenPrinter
2630 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2631 * called from api_spoolss_rffpcnex
2632 ********************************************************************/
2634 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2636 POLICY_HND *handle = &q_u->handle;
2637 uint32 flags = q_u->flags;
2638 uint32 options = q_u->options;
2639 UNISTR2 *localmachine = &q_u->localmachine;
2640 uint32 printerlocal = q_u->printerlocal;
2641 int snum = -1;
2642 SPOOL_NOTIFY_OPTION *option = q_u->option;
2643 struct in_addr client_ip;
2645 /* store the notify value in the printer struct */
2647 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2649 if (!Printer) {
2650 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2651 return WERR_BADFID;
2654 Printer->notify.flags=flags;
2655 Printer->notify.options=options;
2656 Printer->notify.printerlocal=printerlocal;
2658 if (Printer->notify.option)
2659 free_spool_notify_option(&Printer->notify.option);
2661 Printer->notify.option=dup_spool_notify_option(option);
2663 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2664 sizeof(Printer->notify.localmachine)-1);
2666 /* Connect to the client machine and send a ReplyOpenPrinter */
2668 if ( Printer->printer_type == SPLHND_SERVER)
2669 snum = -1;
2670 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2671 !get_printer_snum(p, handle, &snum) )
2672 return WERR_BADFID;
2674 client_ip.s_addr = inet_addr(p->conn->client_address);
2676 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2677 Printer->notify.printerlocal, 1,
2678 &Printer->notify.client_hnd, &client_ip))
2679 return WERR_SERVER_UNAVAILABLE;
2681 Printer->notify.client_connected=True;
2683 return WERR_OK;
2686 /*******************************************************************
2687 * fill a notify_info_data with the servername
2688 ********************************************************************/
2690 void spoolss_notify_server_name(int snum,
2691 SPOOL_NOTIFY_INFO_DATA *data,
2692 print_queue_struct *queue,
2693 NT_PRINTER_INFO_LEVEL *printer,
2694 TALLOC_CTX *mem_ctx)
2696 pstring temp;
2697 uint32 len;
2699 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2701 data->notify_data.data.length = len;
2702 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2704 if (!data->notify_data.data.string) {
2705 data->notify_data.data.length = 0;
2706 return;
2709 memcpy(data->notify_data.data.string, temp, len);
2712 /*******************************************************************
2713 * fill a notify_info_data with the printername (not including the servername).
2714 ********************************************************************/
2716 void spoolss_notify_printer_name(int snum,
2717 SPOOL_NOTIFY_INFO_DATA *data,
2718 print_queue_struct *queue,
2719 NT_PRINTER_INFO_LEVEL *printer,
2720 TALLOC_CTX *mem_ctx)
2722 pstring temp;
2723 uint32 len;
2725 /* the notify name should not contain the \\server\ part */
2726 char *p = strrchr(printer->info_2->printername, '\\');
2728 if (!p) {
2729 p = printer->info_2->printername;
2730 } else {
2731 p++;
2734 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2736 data->notify_data.data.length = len;
2737 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2739 if (!data->notify_data.data.string) {
2740 data->notify_data.data.length = 0;
2741 return;
2744 memcpy(data->notify_data.data.string, temp, len);
2747 /*******************************************************************
2748 * fill a notify_info_data with the servicename
2749 ********************************************************************/
2751 void spoolss_notify_share_name(int snum,
2752 SPOOL_NOTIFY_INFO_DATA *data,
2753 print_queue_struct *queue,
2754 NT_PRINTER_INFO_LEVEL *printer,
2755 TALLOC_CTX *mem_ctx)
2757 pstring temp;
2758 uint32 len;
2760 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2762 data->notify_data.data.length = len;
2763 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2765 if (!data->notify_data.data.string) {
2766 data->notify_data.data.length = 0;
2767 return;
2770 memcpy(data->notify_data.data.string, temp, len);
2773 /*******************************************************************
2774 * fill a notify_info_data with the port name
2775 ********************************************************************/
2777 void spoolss_notify_port_name(int snum,
2778 SPOOL_NOTIFY_INFO_DATA *data,
2779 print_queue_struct *queue,
2780 NT_PRINTER_INFO_LEVEL *printer,
2781 TALLOC_CTX *mem_ctx)
2783 pstring temp;
2784 uint32 len;
2786 /* even if it's strange, that's consistant in all the code */
2788 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2790 data->notify_data.data.length = len;
2791 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2793 if (!data->notify_data.data.string) {
2794 data->notify_data.data.length = 0;
2795 return;
2798 memcpy(data->notify_data.data.string, temp, len);
2801 /*******************************************************************
2802 * fill a notify_info_data with the printername
2803 * but it doesn't exist, have to see what to do
2804 ********************************************************************/
2806 void spoolss_notify_driver_name(int snum,
2807 SPOOL_NOTIFY_INFO_DATA *data,
2808 print_queue_struct *queue,
2809 NT_PRINTER_INFO_LEVEL *printer,
2810 TALLOC_CTX *mem_ctx)
2812 pstring temp;
2813 uint32 len;
2815 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2817 data->notify_data.data.length = len;
2818 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2820 if (!data->notify_data.data.string) {
2821 data->notify_data.data.length = 0;
2822 return;
2825 memcpy(data->notify_data.data.string, temp, len);
2828 /*******************************************************************
2829 * fill a notify_info_data with the comment
2830 ********************************************************************/
2832 void spoolss_notify_comment(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2838 pstring temp;
2839 uint32 len;
2841 if (*printer->info_2->comment == '\0')
2842 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2843 else
2844 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2846 data->notify_data.data.length = len;
2847 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2849 if (!data->notify_data.data.string) {
2850 data->notify_data.data.length = 0;
2851 return;
2854 memcpy(data->notify_data.data.string, temp, len);
2857 /*******************************************************************
2858 * fill a notify_info_data with the comment
2859 * location = "Room 1, floor 2, building 3"
2860 ********************************************************************/
2862 void spoolss_notify_location(int snum,
2863 SPOOL_NOTIFY_INFO_DATA *data,
2864 print_queue_struct *queue,
2865 NT_PRINTER_INFO_LEVEL *printer,
2866 TALLOC_CTX *mem_ctx)
2868 pstring temp;
2869 uint32 len;
2871 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2873 data->notify_data.data.length = len;
2874 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2876 if (!data->notify_data.data.string) {
2877 data->notify_data.data.length = 0;
2878 return;
2881 memcpy(data->notify_data.data.string, temp, len);
2884 /*******************************************************************
2885 * fill a notify_info_data with the device mode
2886 * jfm:xxxx don't to it for know but that's a real problem !!!
2887 ********************************************************************/
2889 static void spoolss_notify_devmode(int snum,
2890 SPOOL_NOTIFY_INFO_DATA *data,
2891 print_queue_struct *queue,
2892 NT_PRINTER_INFO_LEVEL *printer,
2893 TALLOC_CTX *mem_ctx)
2897 /*******************************************************************
2898 * fill a notify_info_data with the separator file name
2899 ********************************************************************/
2901 void spoolss_notify_sepfile(int snum,
2902 SPOOL_NOTIFY_INFO_DATA *data,
2903 print_queue_struct *queue,
2904 NT_PRINTER_INFO_LEVEL *printer,
2905 TALLOC_CTX *mem_ctx)
2907 pstring temp;
2908 uint32 len;
2910 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2912 data->notify_data.data.length = len;
2913 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2915 if (!data->notify_data.data.string) {
2916 data->notify_data.data.length = 0;
2917 return;
2920 memcpy(data->notify_data.data.string, temp, len);
2923 /*******************************************************************
2924 * fill a notify_info_data with the print processor
2925 * jfm:xxxx return always winprint to indicate we don't do anything to it
2926 ********************************************************************/
2928 void spoolss_notify_print_processor(int snum,
2929 SPOOL_NOTIFY_INFO_DATA *data,
2930 print_queue_struct *queue,
2931 NT_PRINTER_INFO_LEVEL *printer,
2932 TALLOC_CTX *mem_ctx)
2934 pstring temp;
2935 uint32 len;
2937 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2939 data->notify_data.data.length = len;
2940 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2942 if (!data->notify_data.data.string) {
2943 data->notify_data.data.length = 0;
2944 return;
2947 memcpy(data->notify_data.data.string, temp, len);
2950 /*******************************************************************
2951 * fill a notify_info_data with the print processor options
2952 * jfm:xxxx send an empty string
2953 ********************************************************************/
2955 void spoolss_notify_parameters(int snum,
2956 SPOOL_NOTIFY_INFO_DATA *data,
2957 print_queue_struct *queue,
2958 NT_PRINTER_INFO_LEVEL *printer,
2959 TALLOC_CTX *mem_ctx)
2961 pstring temp;
2962 uint32 len;
2964 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2966 data->notify_data.data.length = len;
2967 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2969 if (!data->notify_data.data.string) {
2970 data->notify_data.data.length = 0;
2971 return;
2974 memcpy(data->notify_data.data.string, temp, len);
2977 /*******************************************************************
2978 * fill a notify_info_data with the data type
2979 * jfm:xxxx always send RAW as data type
2980 ********************************************************************/
2982 void spoolss_notify_datatype(int snum,
2983 SPOOL_NOTIFY_INFO_DATA *data,
2984 print_queue_struct *queue,
2985 NT_PRINTER_INFO_LEVEL *printer,
2986 TALLOC_CTX *mem_ctx)
2988 pstring temp;
2989 uint32 len;
2991 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2993 data->notify_data.data.length = len;
2994 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2996 if (!data->notify_data.data.string) {
2997 data->notify_data.data.length = 0;
2998 return;
3001 memcpy(data->notify_data.data.string, temp, len);
3004 /*******************************************************************
3005 * fill a notify_info_data with the security descriptor
3006 * jfm:xxxx send an null pointer to say no security desc
3007 * have to implement security before !
3008 ********************************************************************/
3010 static void spoolss_notify_security_desc(int snum,
3011 SPOOL_NOTIFY_INFO_DATA *data,
3012 print_queue_struct *queue,
3013 NT_PRINTER_INFO_LEVEL *printer,
3014 TALLOC_CTX *mem_ctx)
3016 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3017 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3020 /*******************************************************************
3021 * fill a notify_info_data with the attributes
3022 * jfm:xxxx a samba printer is always shared
3023 ********************************************************************/
3025 void spoolss_notify_attributes(int snum,
3026 SPOOL_NOTIFY_INFO_DATA *data,
3027 print_queue_struct *queue,
3028 NT_PRINTER_INFO_LEVEL *printer,
3029 TALLOC_CTX *mem_ctx)
3031 data->notify_data.value[0] = printer->info_2->attributes;
3032 data->notify_data.value[1] = 0;
3035 /*******************************************************************
3036 * fill a notify_info_data with the priority
3037 ********************************************************************/
3039 static void spoolss_notify_priority(int snum,
3040 SPOOL_NOTIFY_INFO_DATA *data,
3041 print_queue_struct *queue,
3042 NT_PRINTER_INFO_LEVEL *printer,
3043 TALLOC_CTX *mem_ctx)
3045 data->notify_data.value[0] = printer->info_2->priority;
3046 data->notify_data.value[1] = 0;
3049 /*******************************************************************
3050 * fill a notify_info_data with the default priority
3051 ********************************************************************/
3053 static void spoolss_notify_default_priority(int snum,
3054 SPOOL_NOTIFY_INFO_DATA *data,
3055 print_queue_struct *queue,
3056 NT_PRINTER_INFO_LEVEL *printer,
3057 TALLOC_CTX *mem_ctx)
3059 data->notify_data.value[0] = printer->info_2->default_priority;
3060 data->notify_data.value[1] = 0;
3063 /*******************************************************************
3064 * fill a notify_info_data with the start time
3065 ********************************************************************/
3067 static void spoolss_notify_start_time(int snum,
3068 SPOOL_NOTIFY_INFO_DATA *data,
3069 print_queue_struct *queue,
3070 NT_PRINTER_INFO_LEVEL *printer,
3071 TALLOC_CTX *mem_ctx)
3073 data->notify_data.value[0] = printer->info_2->starttime;
3074 data->notify_data.value[1] = 0;
3077 /*******************************************************************
3078 * fill a notify_info_data with the until time
3079 ********************************************************************/
3081 static void spoolss_notify_until_time(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0] = printer->info_2->untiltime;
3088 data->notify_data.value[1] = 0;
3091 /*******************************************************************
3092 * fill a notify_info_data with the status
3093 ********************************************************************/
3095 static void spoolss_notify_status(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3101 print_status_struct status;
3103 print_queue_length(snum, &status);
3104 data->notify_data.value[0]=(uint32) status.status;
3105 data->notify_data.value[1] = 0;
3108 /*******************************************************************
3109 * fill a notify_info_data with the number of jobs queued
3110 ********************************************************************/
3112 void spoolss_notify_cjobs(int snum,
3113 SPOOL_NOTIFY_INFO_DATA *data,
3114 print_queue_struct *queue,
3115 NT_PRINTER_INFO_LEVEL *printer,
3116 TALLOC_CTX *mem_ctx)
3118 data->notify_data.value[0] = print_queue_length(snum, NULL);
3119 data->notify_data.value[1] = 0;
3122 /*******************************************************************
3123 * fill a notify_info_data with the average ppm
3124 ********************************************************************/
3126 static void spoolss_notify_average_ppm(int snum,
3127 SPOOL_NOTIFY_INFO_DATA *data,
3128 print_queue_struct *queue,
3129 NT_PRINTER_INFO_LEVEL *printer,
3130 TALLOC_CTX *mem_ctx)
3132 /* always respond 8 pages per minutes */
3133 /* a little hard ! */
3134 data->notify_data.value[0] = printer->info_2->averageppm;
3135 data->notify_data.value[1] = 0;
3138 /*******************************************************************
3139 * fill a notify_info_data with username
3140 ********************************************************************/
3142 static void spoolss_notify_username(int snum,
3143 SPOOL_NOTIFY_INFO_DATA *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3148 pstring temp;
3149 uint32 len;
3151 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3153 data->notify_data.data.length = len;
3154 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3156 if (!data->notify_data.data.string) {
3157 data->notify_data.data.length = 0;
3158 return;
3161 memcpy(data->notify_data.data.string, temp, len);
3164 /*******************************************************************
3165 * fill a notify_info_data with job status
3166 ********************************************************************/
3168 static void spoolss_notify_job_status(int snum,
3169 SPOOL_NOTIFY_INFO_DATA *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer,
3172 TALLOC_CTX *mem_ctx)
3174 data->notify_data.value[0]=nt_printj_status(queue->status);
3175 data->notify_data.value[1] = 0;
3178 /*******************************************************************
3179 * fill a notify_info_data with job name
3180 ********************************************************************/
3182 static void spoolss_notify_job_name(int snum,
3183 SPOOL_NOTIFY_INFO_DATA *data,
3184 print_queue_struct *queue,
3185 NT_PRINTER_INFO_LEVEL *printer,
3186 TALLOC_CTX *mem_ctx)
3188 pstring temp;
3189 uint32 len;
3191 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3193 data->notify_data.data.length = len;
3194 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3196 if (!data->notify_data.data.string) {
3197 data->notify_data.data.length = 0;
3198 return;
3201 memcpy(data->notify_data.data.string, temp, len);
3204 /*******************************************************************
3205 * fill a notify_info_data with job status
3206 ********************************************************************/
3208 static void spoolss_notify_job_status_string(int snum,
3209 SPOOL_NOTIFY_INFO_DATA *data,
3210 print_queue_struct *queue,
3211 NT_PRINTER_INFO_LEVEL *printer,
3212 TALLOC_CTX *mem_ctx)
3215 * Now we're returning job status codes we just return a "" here. JRA.
3218 const char *p = "";
3219 pstring temp;
3220 uint32 len;
3222 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3223 p = "unknown";
3225 switch (queue->status) {
3226 case LPQ_QUEUED:
3227 p = "Queued";
3228 break;
3229 case LPQ_PAUSED:
3230 p = ""; /* NT provides the paused string */
3231 break;
3232 case LPQ_SPOOLING:
3233 p = "Spooling";
3234 break;
3235 case LPQ_PRINTING:
3236 p = "Printing";
3237 break;
3239 #endif /* NO LONGER NEEDED. */
3241 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3243 data->notify_data.data.length = len;
3244 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3246 if (!data->notify_data.data.string) {
3247 data->notify_data.data.length = 0;
3248 return;
3251 memcpy(data->notify_data.data.string, temp, len);
3254 /*******************************************************************
3255 * fill a notify_info_data with job time
3256 ********************************************************************/
3258 static void spoolss_notify_job_time(int snum,
3259 SPOOL_NOTIFY_INFO_DATA *data,
3260 print_queue_struct *queue,
3261 NT_PRINTER_INFO_LEVEL *printer,
3262 TALLOC_CTX *mem_ctx)
3264 data->notify_data.value[0]=0x0;
3265 data->notify_data.value[1]=0;
3268 /*******************************************************************
3269 * fill a notify_info_data with job size
3270 ********************************************************************/
3272 static void spoolss_notify_job_size(int snum,
3273 SPOOL_NOTIFY_INFO_DATA *data,
3274 print_queue_struct *queue,
3275 NT_PRINTER_INFO_LEVEL *printer,
3276 TALLOC_CTX *mem_ctx)
3278 data->notify_data.value[0]=queue->size;
3279 data->notify_data.value[1]=0;
3282 /*******************************************************************
3283 * fill a notify_info_data with page info
3284 ********************************************************************/
3285 static void spoolss_notify_total_pages(int snum,
3286 SPOOL_NOTIFY_INFO_DATA *data,
3287 print_queue_struct *queue,
3288 NT_PRINTER_INFO_LEVEL *printer,
3289 TALLOC_CTX *mem_ctx)
3291 data->notify_data.value[0]=queue->page_count;
3292 data->notify_data.value[1]=0;
3295 /*******************************************************************
3296 * fill a notify_info_data with pages printed info.
3297 ********************************************************************/
3298 static void spoolss_notify_pages_printed(int snum,
3299 SPOOL_NOTIFY_INFO_DATA *data,
3300 print_queue_struct *queue,
3301 NT_PRINTER_INFO_LEVEL *printer,
3302 TALLOC_CTX *mem_ctx)
3304 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3305 data->notify_data.value[1]=0;
3308 /*******************************************************************
3309 Fill a notify_info_data with job position.
3310 ********************************************************************/
3312 static void spoolss_notify_job_position(int snum,
3313 SPOOL_NOTIFY_INFO_DATA *data,
3314 print_queue_struct *queue,
3315 NT_PRINTER_INFO_LEVEL *printer,
3316 TALLOC_CTX *mem_ctx)
3318 data->notify_data.value[0]=queue->job;
3319 data->notify_data.value[1]=0;
3322 /*******************************************************************
3323 Fill a notify_info_data with submitted time.
3324 ********************************************************************/
3326 static void spoolss_notify_submitted_time(int snum,
3327 SPOOL_NOTIFY_INFO_DATA *data,
3328 print_queue_struct *queue,
3329 NT_PRINTER_INFO_LEVEL *printer,
3330 TALLOC_CTX *mem_ctx)
3332 struct tm *t;
3333 uint32 len;
3334 SYSTEMTIME st;
3335 char *p;
3337 t=gmtime(&queue->time);
3339 len = sizeof(SYSTEMTIME);
3341 data->notify_data.data.length = len;
3342 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3344 if (!data->notify_data.data.string) {
3345 data->notify_data.data.length = 0;
3346 return;
3349 make_systemtime(&st, t);
3352 * Systemtime must be linearized as a set of UINT16's.
3353 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3356 p = (char *)data->notify_data.data.string;
3357 SSVAL(p, 0, st.year);
3358 SSVAL(p, 2, st.month);
3359 SSVAL(p, 4, st.dayofweek);
3360 SSVAL(p, 6, st.day);
3361 SSVAL(p, 8, st.hour);
3362 SSVAL(p, 10, st.minute);
3363 SSVAL(p, 12, st.second);
3364 SSVAL(p, 14, st.milliseconds);
3367 struct s_notify_info_data_table
3369 uint16 type;
3370 uint16 field;
3371 const char *name;
3372 uint32 size;
3373 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3374 print_queue_struct *queue,
3375 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3378 /* A table describing the various print notification constants and
3379 whether the notification data is a pointer to a variable sized
3380 buffer, a one value uint32 or a two value uint32. */
3382 static const struct s_notify_info_data_table notify_info_data_table[] =
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3433 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3436 /*******************************************************************
3437 Return the size of info_data structure.
3438 ********************************************************************/
3440 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3442 int i=0;
3444 for (i = 0; i < sizeof(notify_info_data_table); i++)
3446 if ( (notify_info_data_table[i].type == type)
3447 && (notify_info_data_table[i].field == field) )
3449 switch(notify_info_data_table[i].size)
3451 case NOTIFY_ONE_VALUE:
3452 case NOTIFY_TWO_VALUE:
3453 return 1;
3454 case NOTIFY_STRING:
3455 return 2;
3457 /* The only pointer notify data I have seen on
3458 the wire is the submitted time and this has
3459 the notify size set to 4. -tpot */
3461 case NOTIFY_POINTER:
3462 return 4;
3464 case NOTIFY_SECDESC:
3465 return 5;
3470 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3472 return 0;
3475 /*******************************************************************
3476 Return the type of notify_info_data.
3477 ********************************************************************/
3479 static int type_of_notify_info_data(uint16 type, uint16 field)
3481 int i=0;
3483 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3484 if (notify_info_data_table[i].type == type &&
3485 notify_info_data_table[i].field == field)
3486 return notify_info_data_table[i].size;
3489 return False;
3492 /****************************************************************************
3493 ****************************************************************************/
3495 static int search_notify(uint16 type, uint16 field, int *value)
3497 int i;
3499 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3500 if (notify_info_data_table[i].type == type &&
3501 notify_info_data_table[i].field == field &&
3502 notify_info_data_table[i].fn != NULL) {
3503 *value = i;
3504 return True;
3508 return False;
3511 /****************************************************************************
3512 ****************************************************************************/
3514 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3516 info_data->type = type;
3517 info_data->field = field;
3518 info_data->reserved = 0;
3520 info_data->size = size_of_notify_info_data(type, field);
3521 info_data->enc_type = type_of_notify_info_data(type, field);
3523 info_data->id = id;
3528 /*******************************************************************
3530 * fill a notify_info struct with info asked
3532 ********************************************************************/
3534 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3535 snum, SPOOL_NOTIFY_OPTION_TYPE
3536 *option_type, uint32 id,
3537 TALLOC_CTX *mem_ctx)
3539 int field_num,j;
3540 uint16 type;
3541 uint16 field;
3543 SPOOL_NOTIFY_INFO_DATA *current_data;
3544 NT_PRINTER_INFO_LEVEL *printer = NULL;
3545 print_queue_struct *queue=NULL;
3547 type=option_type->type;
3549 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3550 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3551 option_type->count, lp_servicename(snum)));
3553 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3554 return False;
3556 for(field_num=0; field_num<option_type->count; field_num++) {
3557 field = option_type->fields[field_num];
3559 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3561 if (!search_notify(type, field, &j) )
3562 continue;
3564 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3565 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3566 return False;
3569 current_data = &info->data[info->count];
3571 construct_info_data(current_data, type, field, id);
3573 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3574 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3576 notify_info_data_table[j].fn(snum, current_data, queue,
3577 printer, mem_ctx);
3579 info->count++;
3582 free_a_printer(&printer, 2);
3583 return True;
3586 /*******************************************************************
3588 * fill a notify_info struct with info asked
3590 ********************************************************************/
3592 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3593 SPOOL_NOTIFY_INFO *info,
3594 NT_PRINTER_INFO_LEVEL *printer,
3595 int snum, SPOOL_NOTIFY_OPTION_TYPE
3596 *option_type, uint32 id,
3597 TALLOC_CTX *mem_ctx)
3599 int field_num,j;
3600 uint16 type;
3601 uint16 field;
3603 SPOOL_NOTIFY_INFO_DATA *current_data;
3605 DEBUG(4,("construct_notify_jobs_info\n"));
3607 type = option_type->type;
3609 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3610 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3611 option_type->count));
3613 for(field_num=0; field_num<option_type->count; field_num++) {
3614 field = option_type->fields[field_num];
3616 if (!search_notify(type, field, &j) )
3617 continue;
3619 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3620 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3621 return False;
3624 current_data=&(info->data[info->count]);
3626 construct_info_data(current_data, type, field, id);
3627 notify_info_data_table[j].fn(snum, current_data, queue,
3628 printer, mem_ctx);
3629 info->count++;
3632 return True;
3636 * JFM: The enumeration is not that simple, it's even non obvious.
3638 * let's take an example: I want to monitor the PRINTER SERVER for
3639 * the printer's name and the number of jobs currently queued.
3640 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3641 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3643 * I have 3 printers on the back of my server.
3645 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3646 * structures.
3647 * Number Data Id
3648 * 1 printer 1 name 1
3649 * 2 printer 1 cjob 1
3650 * 3 printer 2 name 2
3651 * 4 printer 2 cjob 2
3652 * 5 printer 3 name 3
3653 * 6 printer 3 name 3
3655 * that's the print server case, the printer case is even worse.
3658 /*******************************************************************
3660 * enumerate all printers on the printserver
3661 * fill a notify_info struct with info asked
3663 ********************************************************************/
3665 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3666 SPOOL_NOTIFY_INFO *info,
3667 TALLOC_CTX *mem_ctx)
3669 int snum;
3670 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3671 int n_services=lp_numservices();
3672 int i;
3673 SPOOL_NOTIFY_OPTION *option;
3674 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3676 DEBUG(4,("printserver_notify_info\n"));
3678 if (!Printer)
3679 return WERR_BADFID;
3681 option=Printer->notify.option;
3682 info->version=2;
3683 info->data=NULL;
3684 info->count=0;
3686 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3687 sending a ffpcn() request first */
3689 if ( !option )
3690 return WERR_BADFID;
3692 for (i=0; i<option->count; i++) {
3693 option_type=&(option->ctr.type[i]);
3695 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3696 continue;
3698 for (snum=0; snum<n_services; snum++)
3700 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3701 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3705 #if 0
3707 * Debugging information, don't delete.
3710 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3714 for (i=0; i<info->count; i++) {
3715 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3719 #endif
3721 return WERR_OK;
3724 /*******************************************************************
3726 * fill a notify_info struct with info asked
3728 ********************************************************************/
3730 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3731 TALLOC_CTX *mem_ctx)
3733 int snum;
3734 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3735 int i;
3736 uint32 id;
3737 SPOOL_NOTIFY_OPTION *option;
3738 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3739 int count,j;
3740 print_queue_struct *queue=NULL;
3741 print_status_struct status;
3743 DEBUG(4,("printer_notify_info\n"));
3745 if (!Printer)
3746 return WERR_BADFID;
3748 option=Printer->notify.option;
3749 id = 0x0;
3750 info->version=2;
3751 info->data=NULL;
3752 info->count=0;
3754 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3755 sending a ffpcn() request first */
3757 if ( !option )
3758 return WERR_BADFID;
3760 get_printer_snum(p, hnd, &snum);
3762 for (i=0; i<option->count; i++) {
3763 option_type=&option->ctr.type[i];
3765 switch ( option_type->type ) {
3766 case PRINTER_NOTIFY_TYPE:
3767 if(construct_notify_printer_info(Printer, info, snum,
3768 option_type, id,
3769 mem_ctx))
3770 id--;
3771 break;
3773 case JOB_NOTIFY_TYPE: {
3774 NT_PRINTER_INFO_LEVEL *printer = NULL;
3776 count = print_queue_status(snum, &queue, &status);
3778 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3779 goto done;
3781 for (j=0; j<count; j++) {
3782 construct_notify_jobs_info(&queue[j], info,
3783 printer, snum,
3784 option_type,
3785 queue[j].job,
3786 mem_ctx);
3789 free_a_printer(&printer, 2);
3791 done:
3792 SAFE_FREE(queue);
3793 break;
3799 * Debugging information, don't delete.
3802 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3803 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3804 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3806 for (i=0; i<info->count; i++) {
3807 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3808 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3809 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3812 return WERR_OK;
3815 /********************************************************************
3816 * spoolss_rfnpcnex
3817 ********************************************************************/
3819 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3821 POLICY_HND *handle = &q_u->handle;
3822 SPOOL_NOTIFY_INFO *info = &r_u->info;
3824 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3825 WERROR result = WERR_BADFID;
3827 /* we always have a NOTIFY_INFO struct */
3828 r_u->info_ptr=0x1;
3830 if (!Printer) {
3831 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3832 OUR_HANDLE(handle)));
3833 goto done;
3836 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3839 * We are now using the change value, and
3840 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3841 * I don't have a global notification system, I'm sending back all the
3842 * informations even when _NOTHING_ has changed.
3845 /* We need to keep track of the change value to send back in
3846 RRPCN replies otherwise our updates are ignored. */
3848 Printer->notify.fnpcn = True;
3850 if (Printer->notify.client_connected) {
3851 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3852 Printer->notify.change = q_u->change;
3855 /* just ignore the SPOOL_NOTIFY_OPTION */
3857 switch (Printer->printer_type) {
3858 case SPLHND_SERVER:
3859 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3860 break;
3862 case SPLHND_PRINTER:
3863 result = printer_notify_info(p, handle, info, p->mem_ctx);
3864 break;
3867 Printer->notify.fnpcn = False;
3869 done:
3870 return result;
3873 /********************************************************************
3874 * construct_printer_info_0
3875 * fill a printer_info_0 struct
3876 ********************************************************************/
3878 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3880 pstring chaine;
3881 int count;
3882 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3883 counter_printer_0 *session_counter;
3884 uint32 global_counter;
3885 struct tm *t;
3886 time_t setuptime;
3887 print_status_struct status;
3889 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3890 return False;
3892 count = print_queue_length(snum, &status);
3894 /* check if we already have a counter for this printer */
3895 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3896 if (session_counter->snum == snum)
3897 break;
3900 /* it's the first time, add it to the list */
3901 if (session_counter==NULL) {
3902 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3903 free_a_printer(&ntprinter, 2);
3904 return False;
3906 ZERO_STRUCTP(session_counter);
3907 session_counter->snum=snum;
3908 session_counter->counter=0;
3909 DLIST_ADD(counter_list, session_counter);
3912 /* increment it */
3913 session_counter->counter++;
3915 /* JFM:
3916 * the global_counter should be stored in a TDB as it's common to all the clients
3917 * and should be zeroed on samba startup
3919 global_counter=session_counter->counter;
3921 pstrcpy(chaine,ntprinter->info_2->printername);
3923 init_unistr(&printer->printername, chaine);
3925 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3926 init_unistr(&printer->servername, chaine);
3928 printer->cjobs = count;
3929 printer->total_jobs = 0;
3930 printer->total_bytes = 0;
3932 setuptime = (time_t)ntprinter->info_2->setuptime;
3933 t=gmtime(&setuptime);
3935 printer->year = t->tm_year+1900;
3936 printer->month = t->tm_mon+1;
3937 printer->dayofweek = t->tm_wday;
3938 printer->day = t->tm_mday;
3939 printer->hour = t->tm_hour;
3940 printer->minute = t->tm_min;
3941 printer->second = t->tm_sec;
3942 printer->milliseconds = 0;
3944 printer->global_counter = global_counter;
3945 printer->total_pages = 0;
3947 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3948 printer->major_version = 0x0005; /* NT 5 */
3949 printer->build_version = 0x0893; /* build 2195 */
3951 printer->unknown7 = 0x1;
3952 printer->unknown8 = 0x0;
3953 printer->unknown9 = 0x0;
3954 printer->session_counter = session_counter->counter;
3955 printer->unknown11 = 0x0;
3956 printer->printer_errors = 0x0; /* number of print failure */
3957 printer->unknown13 = 0x0;
3958 printer->unknown14 = 0x1;
3959 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3960 printer->unknown16 = 0x0;
3961 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3962 printer->unknown18 = 0x0;
3963 printer->status = nt_printq_status(status.status);
3964 printer->unknown20 = 0x0;
3965 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3966 printer->unknown22 = 0x0;
3967 printer->unknown23 = 0x6; /* 6 ???*/
3968 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3969 printer->unknown25 = 0;
3970 printer->unknown26 = 0;
3971 printer->unknown27 = 0;
3972 printer->unknown28 = 0;
3973 printer->unknown29 = 0;
3975 free_a_printer(&ntprinter,2);
3976 return (True);
3979 /********************************************************************
3980 * construct_printer_info_1
3981 * fill a printer_info_1 struct
3982 ********************************************************************/
3983 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3985 pstring chaine;
3986 pstring chaine2;
3987 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3989 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3990 return False;
3992 printer->flags=flags;
3994 if (*ntprinter->info_2->comment == '\0') {
3995 init_unistr(&printer->comment, lp_comment(snum));
3996 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3997 ntprinter->info_2->drivername, lp_comment(snum));
3999 else {
4000 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4001 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4002 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4005 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4007 init_unistr(&printer->description, chaine);
4008 init_unistr(&printer->name, chaine2);
4010 free_a_printer(&ntprinter,2);
4012 return True;
4015 /****************************************************************************
4016 Free a DEVMODE struct.
4017 ****************************************************************************/
4019 static void free_dev_mode(DEVICEMODE *dev)
4021 if (dev == NULL)
4022 return;
4024 SAFE_FREE(dev->dev_private);
4025 SAFE_FREE(dev);
4029 /****************************************************************************
4030 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4031 should be valid upon entry
4032 ****************************************************************************/
4034 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4036 if ( !devmode || !ntdevmode )
4037 return False;
4039 init_unistr(&devmode->devicename, ntdevmode->devicename);
4041 init_unistr(&devmode->formname, ntdevmode->formname);
4043 devmode->specversion = ntdevmode->specversion;
4044 devmode->driverversion = ntdevmode->driverversion;
4045 devmode->size = ntdevmode->size;
4046 devmode->driverextra = ntdevmode->driverextra;
4047 devmode->fields = ntdevmode->fields;
4049 devmode->orientation = ntdevmode->orientation;
4050 devmode->papersize = ntdevmode->papersize;
4051 devmode->paperlength = ntdevmode->paperlength;
4052 devmode->paperwidth = ntdevmode->paperwidth;
4053 devmode->scale = ntdevmode->scale;
4054 devmode->copies = ntdevmode->copies;
4055 devmode->defaultsource = ntdevmode->defaultsource;
4056 devmode->printquality = ntdevmode->printquality;
4057 devmode->color = ntdevmode->color;
4058 devmode->duplex = ntdevmode->duplex;
4059 devmode->yresolution = ntdevmode->yresolution;
4060 devmode->ttoption = ntdevmode->ttoption;
4061 devmode->collate = ntdevmode->collate;
4062 devmode->icmmethod = ntdevmode->icmmethod;
4063 devmode->icmintent = ntdevmode->icmintent;
4064 devmode->mediatype = ntdevmode->mediatype;
4065 devmode->dithertype = ntdevmode->dithertype;
4067 if (ntdevmode->nt_dev_private != NULL) {
4068 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4069 return False;
4072 return True;
4075 /****************************************************************************
4076 Create a DEVMODE struct. Returns malloced memory.
4077 ****************************************************************************/
4079 DEVICEMODE *construct_dev_mode(int snum)
4081 NT_PRINTER_INFO_LEVEL *printer = NULL;
4082 DEVICEMODE *devmode = NULL;
4084 DEBUG(7,("construct_dev_mode\n"));
4086 DEBUGADD(8,("getting printer characteristics\n"));
4088 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4089 return NULL;
4091 if ( !printer->info_2->devmode ) {
4092 DEBUG(5, ("BONG! There was no device mode!\n"));
4093 goto done;
4096 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4097 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4098 goto done;
4101 ZERO_STRUCTP(devmode);
4103 DEBUGADD(8,("loading DEVICEMODE\n"));
4105 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4106 free_dev_mode( devmode );
4107 devmode = NULL;
4110 done:
4111 free_a_printer(&printer,2);
4113 return devmode;
4116 /********************************************************************
4117 * construct_printer_info_2
4118 * fill a printer_info_2 struct
4119 ********************************************************************/
4121 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4123 int count;
4124 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4126 print_status_struct status;
4128 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4129 return False;
4131 count = print_queue_length(snum, &status);
4133 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4134 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4135 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4136 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4137 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4139 if (*ntprinter->info_2->comment == '\0')
4140 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4141 else
4142 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4144 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4145 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4146 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4147 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4148 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4150 printer->attributes = ntprinter->info_2->attributes;
4152 printer->priority = ntprinter->info_2->priority; /* priority */
4153 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4154 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4155 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4156 printer->status = nt_printq_status(status.status); /* status */
4157 printer->cjobs = count; /* jobs */
4158 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4160 if ( !(printer->devmode = construct_dev_mode(snum)) )
4161 DEBUG(8, ("Returning NULL Devicemode!\n"));
4163 printer->secdesc = NULL;
4165 if ( ntprinter->info_2->secdesc_buf
4166 && ntprinter->info_2->secdesc_buf->len != 0 )
4168 /* don't use talloc_steal() here unless you do a deep steal of all
4169 the SEC_DESC members */
4171 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4172 ntprinter->info_2->secdesc_buf->sec );
4175 free_a_printer(&ntprinter, 2);
4177 return True;
4180 /********************************************************************
4181 * construct_printer_info_3
4182 * fill a printer_info_3 struct
4183 ********************************************************************/
4185 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4187 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4188 PRINTER_INFO_3 *printer = NULL;
4190 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4191 return False;
4193 *pp_printer = NULL;
4194 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4195 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4196 return False;
4199 ZERO_STRUCTP(printer);
4201 /* These are the components of the SD we are returning. */
4203 printer->flags = 0x4;
4205 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4206 /* don't use talloc_steal() here unless you do a deep steal of all
4207 the SEC_DESC members */
4209 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4210 ntprinter->info_2->secdesc_buf->sec );
4213 free_a_printer(&ntprinter, 2);
4215 *pp_printer = printer;
4216 return True;
4219 /********************************************************************
4220 * construct_printer_info_4
4221 * fill a printer_info_4 struct
4222 ********************************************************************/
4224 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4226 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4228 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4229 return False;
4231 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4232 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4233 printer->attributes = ntprinter->info_2->attributes;
4235 free_a_printer(&ntprinter, 2);
4236 return True;
4239 /********************************************************************
4240 * construct_printer_info_5
4241 * fill a printer_info_5 struct
4242 ********************************************************************/
4244 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4246 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4248 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4249 return False;
4251 init_unistr(&printer->printername, ntprinter->info_2->printername);
4252 init_unistr(&printer->portname, ntprinter->info_2->portname);
4253 printer->attributes = ntprinter->info_2->attributes;
4255 /* these two are not used by NT+ according to MSDN */
4257 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4258 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4260 free_a_printer(&ntprinter, 2);
4262 return True;
4265 /********************************************************************
4266 * construct_printer_info_7
4267 * fill a printer_info_7 struct
4268 ********************************************************************/
4270 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4272 char *guid_str = NULL;
4273 struct uuid guid;
4275 if (is_printer_published(print_hnd, snum, &guid)) {
4276 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4277 strupper_m(guid_str);
4278 init_unistr(&printer->guid, guid_str);
4279 printer->action = SPOOL_DS_PUBLISH;
4280 } else {
4281 init_unistr(&printer->guid, "");
4282 printer->action = SPOOL_DS_UNPUBLISH;
4285 return True;
4288 /********************************************************************
4289 Spoolss_enumprinters.
4290 ********************************************************************/
4292 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4294 int snum;
4295 int i;
4296 int n_services=lp_numservices();
4297 PRINTER_INFO_1 *printers=NULL;
4298 PRINTER_INFO_1 current_prt;
4299 WERROR result = WERR_OK;
4301 DEBUG(4,("enum_all_printers_info_1\n"));
4303 for (snum=0; snum<n_services; snum++) {
4304 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4305 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4307 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4308 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4309 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4310 *returned=0;
4311 return WERR_NOMEM;
4313 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4315 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4316 (*returned)++;
4321 /* check the required size. */
4322 for (i=0; i<*returned; i++)
4323 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4325 if (*needed > offered) {
4326 result = WERR_INSUFFICIENT_BUFFER;
4327 goto out;
4330 if (!rpcbuf_alloc_size(buffer, *needed)) {
4331 result = WERR_NOMEM;
4332 goto out;
4335 /* fill the buffer with the structures */
4336 for (i=0; i<*returned; i++)
4337 smb_io_printer_info_1("", buffer, &printers[i], 0);
4339 out:
4340 /* clear memory */
4342 SAFE_FREE(printers);
4344 if ( !W_ERROR_IS_OK(result) )
4345 *returned = 0;
4347 return result;
4350 /********************************************************************
4351 enum_all_printers_info_1_local.
4352 *********************************************************************/
4354 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4356 DEBUG(4,("enum_all_printers_info_1_local\n"));
4358 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4361 /********************************************************************
4362 enum_all_printers_info_1_name.
4363 *********************************************************************/
4365 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4367 char *s = name;
4369 DEBUG(4,("enum_all_printers_info_1_name\n"));
4371 if ((name[0] == '\\') && (name[1] == '\\'))
4372 s = name + 2;
4374 if (is_myname_or_ipaddr(s)) {
4375 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4377 else
4378 return WERR_INVALID_NAME;
4381 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4382 /********************************************************************
4383 enum_all_printers_info_1_remote.
4384 *********************************************************************/
4386 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4388 PRINTER_INFO_1 *printer;
4389 fstring printername;
4390 fstring desc;
4391 fstring comment;
4392 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4393 WERROR result = WERR_OK;
4395 /* JFM: currently it's more a place holder than anything else.
4396 * In the spooler world there is a notion of server registration.
4397 * the print servers are registered on the PDC (in the same domain)
4399 * We should have a TDB here. The registration is done thru an
4400 * undocumented RPC call.
4403 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4404 return WERR_NOMEM;
4406 *returned=1;
4408 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4409 slprintf(desc, sizeof(desc)-1,"%s", name);
4410 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4412 init_unistr(&printer->description, desc);
4413 init_unistr(&printer->name, printername);
4414 init_unistr(&printer->comment, comment);
4415 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4417 /* check the required size. */
4418 *needed += spoolss_size_printer_info_1(printer);
4420 if (*needed > offered) {
4421 result = WERR_INSUFFICIENT_BUFFER;
4422 goto out;
4425 if (!rpcbuf_alloc_size(buffer, *needed)) {
4426 result = WERR_NOMEM;
4427 goto out;
4430 /* fill the buffer with the structures */
4431 smb_io_printer_info_1("", buffer, printer, 0);
4433 out:
4434 /* clear memory */
4435 SAFE_FREE(printer);
4437 if ( !W_ERROR_IS_OK(result) )
4438 *returned = 0;
4440 return result;
4443 #endif
4445 /********************************************************************
4446 enum_all_printers_info_1_network.
4447 *********************************************************************/
4449 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4451 char *s = name;
4453 DEBUG(4,("enum_all_printers_info_1_network\n"));
4455 /* If we respond to a enum_printers level 1 on our name with flags
4456 set to PRINTER_ENUM_REMOTE with a list of printers then these
4457 printers incorrectly appear in the APW browse list.
4458 Specifically the printers for the server appear at the workgroup
4459 level where all the other servers in the domain are
4460 listed. Windows responds to this call with a
4461 WERR_CAN_NOT_COMPLETE so we should do the same. */
4463 if (name[0] == '\\' && name[1] == '\\')
4464 s = name + 2;
4466 if (is_myname_or_ipaddr(s))
4467 return WERR_CAN_NOT_COMPLETE;
4469 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4472 /********************************************************************
4473 * api_spoolss_enumprinters
4475 * called from api_spoolss_enumprinters (see this to understand)
4476 ********************************************************************/
4478 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4480 int snum;
4481 int i;
4482 int n_services=lp_numservices();
4483 PRINTER_INFO_2 *printers=NULL;
4484 PRINTER_INFO_2 current_prt;
4485 WERROR result = WERR_OK;
4487 *returned = 0;
4489 for (snum=0; snum<n_services; snum++) {
4490 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4491 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4493 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4494 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4495 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4496 *returned = 0;
4497 return WERR_NOMEM;
4500 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4502 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4504 (*returned)++;
4509 /* check the required size. */
4510 for (i=0; i<*returned; i++)
4511 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4513 if (*needed > offered) {
4514 result = WERR_INSUFFICIENT_BUFFER;
4515 goto out;
4518 if (!rpcbuf_alloc_size(buffer, *needed)) {
4519 result = WERR_NOMEM;
4520 goto out;
4523 /* fill the buffer with the structures */
4524 for (i=0; i<*returned; i++)
4525 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4527 out:
4528 /* clear memory */
4530 for (i=0; i<*returned; i++)
4531 free_devmode(printers[i].devmode);
4533 SAFE_FREE(printers);
4535 if ( !W_ERROR_IS_OK(result) )
4536 *returned = 0;
4538 return result;
4541 /********************************************************************
4542 * handle enumeration of printers at level 1
4543 ********************************************************************/
4545 static WERROR enumprinters_level1( uint32 flags, fstring name,
4546 RPC_BUFFER *buffer, uint32 offered,
4547 uint32 *needed, uint32 *returned)
4549 /* Not all the flags are equals */
4551 if (flags & PRINTER_ENUM_LOCAL)
4552 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4554 if (flags & PRINTER_ENUM_NAME)
4555 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4557 #if 0 /* JERRY - disabled for now */
4558 if (flags & PRINTER_ENUM_REMOTE)
4559 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4560 #endif
4562 if (flags & PRINTER_ENUM_NETWORK)
4563 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4565 return WERR_OK; /* NT4sp5 does that */
4568 /********************************************************************
4569 * handle enumeration of printers at level 2
4570 ********************************************************************/
4572 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4573 RPC_BUFFER *buffer, uint32 offered,
4574 uint32 *needed, uint32 *returned)
4576 char *s = servername;
4578 if (flags & PRINTER_ENUM_LOCAL) {
4579 return enum_all_printers_info_2(buffer, offered, needed, returned);
4582 if (flags & PRINTER_ENUM_NAME) {
4583 if ((servername[0] == '\\') && (servername[1] == '\\'))
4584 s = servername + 2;
4585 if (is_myname_or_ipaddr(s))
4586 return enum_all_printers_info_2(buffer, offered, needed, returned);
4587 else
4588 return WERR_INVALID_NAME;
4591 if (flags & PRINTER_ENUM_REMOTE)
4592 return WERR_UNKNOWN_LEVEL;
4594 return WERR_OK;
4597 /********************************************************************
4598 * handle enumeration of printers at level 5
4599 ********************************************************************/
4601 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4602 RPC_BUFFER *buffer, uint32 offered,
4603 uint32 *needed, uint32 *returned)
4605 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4606 return WERR_OK;
4609 /********************************************************************
4610 * api_spoolss_enumprinters
4612 * called from api_spoolss_enumprinters (see this to understand)
4613 ********************************************************************/
4615 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4617 uint32 flags = q_u->flags;
4618 UNISTR2 *servername = &q_u->servername;
4619 uint32 level = q_u->level;
4620 RPC_BUFFER *buffer = NULL;
4621 uint32 offered = q_u->offered;
4622 uint32 *needed = &r_u->needed;
4623 uint32 *returned = &r_u->returned;
4625 fstring name;
4627 /* that's an [in out] buffer */
4629 if (!q_u->buffer) {
4630 return WERR_INVALID_PARAM;
4633 rpcbuf_move(q_u->buffer, &r_u->buffer);
4634 buffer = r_u->buffer;
4636 DEBUG(4,("_spoolss_enumprinters\n"));
4638 *needed=0;
4639 *returned=0;
4642 * Level 1:
4643 * flags==PRINTER_ENUM_NAME
4644 * if name=="" then enumerates all printers
4645 * if name!="" then enumerate the printer
4646 * flags==PRINTER_ENUM_REMOTE
4647 * name is NULL, enumerate printers
4648 * Level 2: name!="" enumerates printers, name can't be NULL
4649 * Level 3: doesn't exist
4650 * Level 4: does a local registry lookup
4651 * Level 5: same as Level 2
4654 unistr2_to_ascii(name, servername, sizeof(name)-1);
4655 strupper_m(name);
4657 switch (level) {
4658 case 1:
4659 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4660 case 2:
4661 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4662 case 5:
4663 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4664 case 3:
4665 case 4:
4666 break;
4668 return WERR_UNKNOWN_LEVEL;
4671 /****************************************************************************
4672 ****************************************************************************/
4674 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4676 PRINTER_INFO_0 *printer=NULL;
4677 WERROR result = WERR_OK;
4679 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4680 return WERR_NOMEM;
4682 construct_printer_info_0(print_hnd, printer, snum);
4684 /* check the required size. */
4685 *needed += spoolss_size_printer_info_0(printer);
4687 if (*needed > offered) {
4688 result = WERR_INSUFFICIENT_BUFFER;
4689 goto out;
4692 if (!rpcbuf_alloc_size(buffer, *needed)) {
4693 result = WERR_NOMEM;
4694 goto out;
4697 /* fill the buffer with the structures */
4698 smb_io_printer_info_0("", buffer, printer, 0);
4700 out:
4701 /* clear memory */
4703 SAFE_FREE(printer);
4705 return result;
4708 /****************************************************************************
4709 ****************************************************************************/
4711 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4713 PRINTER_INFO_1 *printer=NULL;
4714 WERROR result = WERR_OK;
4716 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4717 return WERR_NOMEM;
4719 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4721 /* check the required size. */
4722 *needed += spoolss_size_printer_info_1(printer);
4724 if (*needed > offered) {
4725 result = WERR_INSUFFICIENT_BUFFER;
4726 goto out;
4729 if (!rpcbuf_alloc_size(buffer, *needed)) {
4730 result = WERR_NOMEM;
4731 goto out;
4734 /* fill the buffer with the structures */
4735 smb_io_printer_info_1("", buffer, printer, 0);
4737 out:
4738 /* clear memory */
4739 SAFE_FREE(printer);
4741 return result;
4744 /****************************************************************************
4745 ****************************************************************************/
4747 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4749 PRINTER_INFO_2 *printer=NULL;
4750 WERROR result = WERR_OK;
4752 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4753 return WERR_NOMEM;
4755 construct_printer_info_2(print_hnd, printer, snum);
4757 /* check the required size. */
4758 *needed += spoolss_size_printer_info_2(printer);
4760 if (*needed > offered) {
4761 result = WERR_INSUFFICIENT_BUFFER;
4762 goto out;
4765 if (!rpcbuf_alloc_size(buffer, *needed)) {
4766 result = WERR_NOMEM;
4767 goto out;
4770 /* fill the buffer with the structures */
4771 if (!smb_io_printer_info_2("", buffer, printer, 0))
4772 result = WERR_NOMEM;
4774 out:
4775 /* clear memory */
4776 free_printer_info_2(printer);
4778 return result;
4781 /****************************************************************************
4782 ****************************************************************************/
4784 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4786 PRINTER_INFO_3 *printer=NULL;
4787 WERROR result = WERR_OK;
4789 if (!construct_printer_info_3(print_hnd, &printer, snum))
4790 return WERR_NOMEM;
4792 /* check the required size. */
4793 *needed += spoolss_size_printer_info_3(printer);
4795 if (*needed > offered) {
4796 result = WERR_INSUFFICIENT_BUFFER;
4797 goto out;
4800 if (!rpcbuf_alloc_size(buffer, *needed)) {
4801 result = WERR_NOMEM;
4802 goto out;
4805 /* fill the buffer with the structures */
4806 smb_io_printer_info_3("", buffer, printer, 0);
4808 out:
4809 /* clear memory */
4810 free_printer_info_3(printer);
4812 return result;
4815 /****************************************************************************
4816 ****************************************************************************/
4818 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4820 PRINTER_INFO_4 *printer=NULL;
4821 WERROR result = WERR_OK;
4823 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4824 return WERR_NOMEM;
4826 if (!construct_printer_info_4(print_hnd, printer, snum))
4827 return WERR_NOMEM;
4829 /* check the required size. */
4830 *needed += spoolss_size_printer_info_4(printer);
4832 if (*needed > offered) {
4833 result = WERR_INSUFFICIENT_BUFFER;
4834 goto out;
4837 if (!rpcbuf_alloc_size(buffer, *needed)) {
4838 result = WERR_NOMEM;
4839 goto out;
4842 /* fill the buffer with the structures */
4843 smb_io_printer_info_4("", buffer, printer, 0);
4845 out:
4846 /* clear memory */
4847 free_printer_info_4(printer);
4849 return result;
4852 /****************************************************************************
4853 ****************************************************************************/
4855 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4857 PRINTER_INFO_5 *printer=NULL;
4858 WERROR result = WERR_OK;
4860 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4861 return WERR_NOMEM;
4863 if (!construct_printer_info_5(print_hnd, printer, snum))
4864 return WERR_NOMEM;
4866 /* check the required size. */
4867 *needed += spoolss_size_printer_info_5(printer);
4869 if (*needed > offered) {
4870 result = WERR_INSUFFICIENT_BUFFER;
4871 goto out;
4874 if (!rpcbuf_alloc_size(buffer, *needed)) {
4875 result = WERR_NOMEM;
4876 goto out;
4879 /* fill the buffer with the structures */
4880 smb_io_printer_info_5("", buffer, printer, 0);
4882 out:
4883 /* clear memory */
4884 free_printer_info_5(printer);
4886 return result;
4889 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4891 PRINTER_INFO_7 *printer=NULL;
4892 WERROR result = WERR_OK;
4894 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4895 return WERR_NOMEM;
4897 if (!construct_printer_info_7(print_hnd, printer, snum))
4898 return WERR_NOMEM;
4900 /* check the required size. */
4901 *needed += spoolss_size_printer_info_7(printer);
4903 if (*needed > offered) {
4904 result = WERR_INSUFFICIENT_BUFFER;
4905 goto out;
4908 if (!rpcbuf_alloc_size(buffer, *needed)) {
4909 result = WERR_NOMEM;
4910 goto out;
4914 /* fill the buffer with the structures */
4915 smb_io_printer_info_7("", buffer, printer, 0);
4917 out:
4918 /* clear memory */
4919 free_printer_info_7(printer);
4921 return result;
4924 /****************************************************************************
4925 ****************************************************************************/
4927 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4929 POLICY_HND *handle = &q_u->handle;
4930 uint32 level = q_u->level;
4931 RPC_BUFFER *buffer = NULL;
4932 uint32 offered = q_u->offered;
4933 uint32 *needed = &r_u->needed;
4934 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4936 int snum;
4938 /* that's an [in out] buffer */
4940 if (!q_u->buffer) {
4941 return WERR_INVALID_PARAM;
4944 rpcbuf_move(q_u->buffer, &r_u->buffer);
4945 buffer = r_u->buffer;
4947 *needed=0;
4949 if (!get_printer_snum(p, handle, &snum))
4950 return WERR_BADFID;
4952 switch (level) {
4953 case 0:
4954 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4955 case 1:
4956 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4957 case 2:
4958 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4959 case 3:
4960 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4961 case 4:
4962 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4963 case 5:
4964 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4965 case 7:
4966 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4968 return WERR_UNKNOWN_LEVEL;
4971 /********************************************************************
4972 * fill a DRIVER_INFO_1 struct
4973 ********************************************************************/
4975 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4977 init_unistr( &info->name, driver.info_3->name);
4980 /********************************************************************
4981 * construct_printer_driver_info_1
4982 ********************************************************************/
4984 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4986 NT_PRINTER_INFO_LEVEL *printer = NULL;
4987 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4989 ZERO_STRUCT(driver);
4991 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4992 return WERR_INVALID_PRINTER_NAME;
4994 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4995 return WERR_UNKNOWN_PRINTER_DRIVER;
4997 fill_printer_driver_info_1(info, driver, servername, architecture);
4999 free_a_printer(&printer,2);
5001 return WERR_OK;
5004 /********************************************************************
5005 * construct_printer_driver_info_2
5006 * fill a printer_info_2 struct
5007 ********************************************************************/
5009 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5011 pstring temp;
5013 info->version=driver.info_3->cversion;
5015 init_unistr( &info->name, driver.info_3->name );
5016 init_unistr( &info->architecture, driver.info_3->environment );
5019 if (strlen(driver.info_3->driverpath)) {
5020 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5021 init_unistr( &info->driverpath, temp );
5022 } else
5023 init_unistr( &info->driverpath, "" );
5025 if (strlen(driver.info_3->datafile)) {
5026 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5027 init_unistr( &info->datafile, temp );
5028 } else
5029 init_unistr( &info->datafile, "" );
5031 if (strlen(driver.info_3->configfile)) {
5032 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5033 init_unistr( &info->configfile, temp );
5034 } else
5035 init_unistr( &info->configfile, "" );
5038 /********************************************************************
5039 * construct_printer_driver_info_2
5040 * fill a printer_info_2 struct
5041 ********************************************************************/
5043 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5045 NT_PRINTER_INFO_LEVEL *printer = NULL;
5046 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5048 ZERO_STRUCT(printer);
5049 ZERO_STRUCT(driver);
5051 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5052 return WERR_INVALID_PRINTER_NAME;
5054 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5055 return WERR_UNKNOWN_PRINTER_DRIVER;
5057 fill_printer_driver_info_2(info, driver, servername);
5059 free_a_printer(&printer,2);
5061 return WERR_OK;
5064 /********************************************************************
5065 * copy a strings array and convert to UNICODE
5067 * convert an array of ascii string to a UNICODE string
5068 ********************************************************************/
5070 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5072 int i=0;
5073 int j=0;
5074 const char *v;
5075 pstring line;
5077 DEBUG(6,("init_unistr_array\n"));
5078 *uni_array=NULL;
5080 while (True)
5082 if ( !char_array )
5083 v = "";
5084 else
5086 v = char_array[i];
5087 if (!v)
5088 v = ""; /* hack to handle null lists */
5091 /* hack to allow this to be used in places other than when generating
5092 the list of dependent files */
5094 if ( servername )
5095 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5096 else
5097 pstrcpy( line, v );
5099 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5101 /* add one extra unit16 for the second terminating NULL */
5103 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5104 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5105 return 0;
5108 if ( !strlen(v) )
5109 break;
5111 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5112 i++;
5115 if (*uni_array) {
5116 /* special case for ""; we need to add both NULL's here */
5117 if (!j)
5118 (*uni_array)[j++]=0x0000;
5119 (*uni_array)[j]=0x0000;
5122 DEBUGADD(6,("last one:done\n"));
5124 /* return size of array in uint16's */
5126 return j+1;
5129 /********************************************************************
5130 * construct_printer_info_3
5131 * fill a printer_info_3 struct
5132 ********************************************************************/
5134 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5136 pstring temp;
5138 ZERO_STRUCTP(info);
5140 info->version=driver.info_3->cversion;
5142 init_unistr( &info->name, driver.info_3->name );
5143 init_unistr( &info->architecture, driver.info_3->environment );
5145 if (strlen(driver.info_3->driverpath)) {
5146 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5147 init_unistr( &info->driverpath, temp );
5148 } else
5149 init_unistr( &info->driverpath, "" );
5151 if (strlen(driver.info_3->datafile)) {
5152 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5153 init_unistr( &info->datafile, temp );
5154 } else
5155 init_unistr( &info->datafile, "" );
5157 if (strlen(driver.info_3->configfile)) {
5158 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5159 init_unistr( &info->configfile, temp );
5160 } else
5161 init_unistr( &info->configfile, "" );
5163 if (strlen(driver.info_3->helpfile)) {
5164 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5165 init_unistr( &info->helpfile, temp );
5166 } else
5167 init_unistr( &info->helpfile, "" );
5169 init_unistr( &info->monitorname, driver.info_3->monitorname );
5170 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5172 info->dependentfiles=NULL;
5173 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5176 /********************************************************************
5177 * construct_printer_info_3
5178 * fill a printer_info_3 struct
5179 ********************************************************************/
5181 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5183 NT_PRINTER_INFO_LEVEL *printer = NULL;
5184 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5185 WERROR status;
5186 ZERO_STRUCT(driver);
5188 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5189 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5190 if (!W_ERROR_IS_OK(status))
5191 return WERR_INVALID_PRINTER_NAME;
5193 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5194 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5196 #if 0 /* JERRY */
5199 * I put this code in during testing. Helpful when commenting out the
5200 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5201 * as win2k always queries the driver using an infor level of 6.
5202 * I've left it in (but ifdef'd out) because I'll probably
5203 * use it in experimentation again in the future. --jerry 22/01/2002
5206 if (!W_ERROR_IS_OK(status)) {
5208 * Is this a W2k client ?
5210 if (version == 3) {
5211 /* Yes - try again with a WinNT driver. */
5212 version = 2;
5213 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5214 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5216 #endif
5218 if (!W_ERROR_IS_OK(status)) {
5219 free_a_printer(&printer,2);
5220 return WERR_UNKNOWN_PRINTER_DRIVER;
5223 #if 0 /* JERRY */
5225 #endif
5228 fill_printer_driver_info_3(info, driver, servername);
5230 free_a_printer(&printer,2);
5232 return WERR_OK;
5235 /********************************************************************
5236 * construct_printer_info_6
5237 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5238 ********************************************************************/
5240 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5242 pstring temp;
5243 fstring nullstr;
5245 ZERO_STRUCTP(info);
5246 memset(&nullstr, '\0', sizeof(fstring));
5248 info->version=driver.info_3->cversion;
5250 init_unistr( &info->name, driver.info_3->name );
5251 init_unistr( &info->architecture, driver.info_3->environment );
5253 if (strlen(driver.info_3->driverpath)) {
5254 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5255 init_unistr( &info->driverpath, temp );
5256 } else
5257 init_unistr( &info->driverpath, "" );
5259 if (strlen(driver.info_3->datafile)) {
5260 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5261 init_unistr( &info->datafile, temp );
5262 } else
5263 init_unistr( &info->datafile, "" );
5265 if (strlen(driver.info_3->configfile)) {
5266 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5267 init_unistr( &info->configfile, temp );
5268 } else
5269 init_unistr( &info->configfile, "" );
5271 if (strlen(driver.info_3->helpfile)) {
5272 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5273 init_unistr( &info->helpfile, temp );
5274 } else
5275 init_unistr( &info->helpfile, "" );
5277 init_unistr( &info->monitorname, driver.info_3->monitorname );
5278 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5280 info->dependentfiles = NULL;
5281 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5283 info->previousdrivernames=NULL;
5284 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5286 info->driver_date.low=0;
5287 info->driver_date.high=0;
5289 info->padding=0;
5290 info->driver_version_low=0;
5291 info->driver_version_high=0;
5293 init_unistr( &info->mfgname, "");
5294 init_unistr( &info->oem_url, "");
5295 init_unistr( &info->hardware_id, "");
5296 init_unistr( &info->provider, "");
5299 /********************************************************************
5300 * construct_printer_info_6
5301 * fill a printer_info_6 struct
5302 ********************************************************************/
5304 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5305 fstring servername, fstring architecture, uint32 version)
5307 NT_PRINTER_INFO_LEVEL *printer = NULL;
5308 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5309 WERROR status;
5311 ZERO_STRUCT(driver);
5313 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5315 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5317 if (!W_ERROR_IS_OK(status))
5318 return WERR_INVALID_PRINTER_NAME;
5320 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5322 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5324 if (!W_ERROR_IS_OK(status))
5327 * Is this a W2k client ?
5330 if (version < 3) {
5331 free_a_printer(&printer,2);
5332 return WERR_UNKNOWN_PRINTER_DRIVER;
5335 /* Yes - try again with a WinNT driver. */
5336 version = 2;
5337 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5338 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5339 if (!W_ERROR_IS_OK(status)) {
5340 free_a_printer(&printer,2);
5341 return WERR_UNKNOWN_PRINTER_DRIVER;
5345 fill_printer_driver_info_6(info, driver, servername);
5347 free_a_printer(&printer,2);
5348 free_a_printer_driver(driver, 3);
5350 return WERR_OK;
5353 /****************************************************************************
5354 ****************************************************************************/
5356 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5358 SAFE_FREE(info->dependentfiles);
5361 /****************************************************************************
5362 ****************************************************************************/
5364 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5366 SAFE_FREE(info->dependentfiles);
5369 /****************************************************************************
5370 ****************************************************************************/
5372 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5374 DRIVER_INFO_1 *info=NULL;
5375 WERROR result;
5377 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5378 return WERR_NOMEM;
5380 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5381 if (!W_ERROR_IS_OK(result))
5382 goto out;
5384 /* check the required size. */
5385 *needed += spoolss_size_printer_driver_info_1(info);
5387 if (*needed > offered) {
5388 result = WERR_INSUFFICIENT_BUFFER;
5389 goto out;
5392 if (!rpcbuf_alloc_size(buffer, *needed)) {
5393 result = WERR_NOMEM;
5394 goto out;
5397 /* fill the buffer with the structures */
5398 smb_io_printer_driver_info_1("", buffer, info, 0);
5400 out:
5401 /* clear memory */
5402 SAFE_FREE(info);
5404 return result;
5407 /****************************************************************************
5408 ****************************************************************************/
5410 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5412 DRIVER_INFO_2 *info=NULL;
5413 WERROR result;
5415 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5416 return WERR_NOMEM;
5418 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5419 if (!W_ERROR_IS_OK(result))
5420 goto out;
5422 /* check the required size. */
5423 *needed += spoolss_size_printer_driver_info_2(info);
5425 if (*needed > offered) {
5426 result = WERR_INSUFFICIENT_BUFFER;
5427 goto out;
5430 if (!rpcbuf_alloc_size(buffer, *needed)) {
5431 result = WERR_NOMEM;
5432 goto out;
5435 /* fill the buffer with the structures */
5436 smb_io_printer_driver_info_2("", buffer, info, 0);
5438 out:
5439 /* clear memory */
5440 SAFE_FREE(info);
5442 return result;
5445 /****************************************************************************
5446 ****************************************************************************/
5448 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5450 DRIVER_INFO_3 info;
5451 WERROR result;
5453 ZERO_STRUCT(info);
5455 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5456 if (!W_ERROR_IS_OK(result))
5457 goto out;
5459 /* check the required size. */
5460 *needed += spoolss_size_printer_driver_info_3(&info);
5462 if (*needed > offered) {
5463 result = WERR_INSUFFICIENT_BUFFER;
5464 goto out;
5467 if (!rpcbuf_alloc_size(buffer, *needed)) {
5468 result = WERR_NOMEM;
5469 goto out;
5472 /* fill the buffer with the structures */
5473 smb_io_printer_driver_info_3("", buffer, &info, 0);
5475 out:
5476 free_printer_driver_info_3(&info);
5478 return result;
5481 /****************************************************************************
5482 ****************************************************************************/
5484 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5486 DRIVER_INFO_6 info;
5487 WERROR result;
5489 ZERO_STRUCT(info);
5491 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5492 if (!W_ERROR_IS_OK(result))
5493 goto out;
5495 /* check the required size. */
5496 *needed += spoolss_size_printer_driver_info_6(&info);
5498 if (*needed > offered) {
5499 result = WERR_INSUFFICIENT_BUFFER;
5500 goto out;
5503 if (!rpcbuf_alloc_size(buffer, *needed)) {
5504 result = WERR_NOMEM;
5505 goto out;
5508 /* fill the buffer with the structures */
5509 smb_io_printer_driver_info_6("", buffer, &info, 0);
5511 out:
5512 free_printer_driver_info_6(&info);
5514 return result;
5517 /****************************************************************************
5518 ****************************************************************************/
5520 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5522 POLICY_HND *handle = &q_u->handle;
5523 UNISTR2 *uni_arch = &q_u->architecture;
5524 uint32 level = q_u->level;
5525 uint32 clientmajorversion = q_u->clientmajorversion;
5526 RPC_BUFFER *buffer = NULL;
5527 uint32 offered = q_u->offered;
5528 uint32 *needed = &r_u->needed;
5529 uint32 *servermajorversion = &r_u->servermajorversion;
5530 uint32 *serverminorversion = &r_u->serverminorversion;
5531 Printer_entry *printer;
5533 fstring servername;
5534 fstring architecture;
5535 int snum;
5537 /* that's an [in out] buffer */
5539 if (!q_u->buffer) {
5540 return WERR_INVALID_PARAM;
5543 rpcbuf_move(q_u->buffer, &r_u->buffer);
5544 buffer = r_u->buffer;
5546 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5548 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5549 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5550 return WERR_INVALID_PRINTER_NAME;
5553 *needed = 0;
5554 *servermajorversion = 0;
5555 *serverminorversion = 0;
5557 fstrcpy(servername, get_server_name( printer ));
5558 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5560 if (!get_printer_snum(p, handle, &snum))
5561 return WERR_BADFID;
5563 switch (level) {
5564 case 1:
5565 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5566 case 2:
5567 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5568 case 3:
5569 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5570 case 6:
5571 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5572 #if 0 /* JERRY */
5573 case 101:
5574 /* apparently this call is the equivalent of
5575 EnumPrinterDataEx() for the DsDriver key */
5576 break;
5577 #endif
5580 return WERR_UNKNOWN_LEVEL;
5583 /****************************************************************************
5584 ****************************************************************************/
5586 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5588 POLICY_HND *handle = &q_u->handle;
5590 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5592 if (!Printer) {
5593 DEBUG(3,("Error in startpageprinter printer handle\n"));
5594 return WERR_BADFID;
5597 Printer->page_started=True;
5598 return WERR_OK;
5601 /****************************************************************************
5602 ****************************************************************************/
5604 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5606 POLICY_HND *handle = &q_u->handle;
5607 int snum;
5609 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5611 if (!Printer) {
5612 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5613 return WERR_BADFID;
5616 if (!get_printer_snum(p, handle, &snum))
5617 return WERR_BADFID;
5619 Printer->page_started=False;
5620 print_job_endpage(snum, Printer->jobid);
5622 return WERR_OK;
5625 /********************************************************************
5626 * api_spoolss_getprinter
5627 * called from the spoolss dispatcher
5629 ********************************************************************/
5631 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5633 POLICY_HND *handle = &q_u->handle;
5634 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5635 uint32 *jobid = &r_u->jobid;
5637 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5638 int snum;
5639 pstring jobname;
5640 fstring datatype;
5641 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5642 struct current_user user;
5644 if (!Printer) {
5645 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5646 return WERR_BADFID;
5649 get_current_user(&user, p);
5652 * a nice thing with NT is it doesn't listen to what you tell it.
5653 * when asked to send _only_ RAW datas, it tries to send datas
5654 * in EMF format.
5656 * So I add checks like in NT Server ...
5659 if (info_1->p_datatype != 0) {
5660 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5661 if (strcmp(datatype, "RAW") != 0) {
5662 (*jobid)=0;
5663 return WERR_INVALID_DATATYPE;
5667 /* get the share number of the printer */
5668 if (!get_printer_snum(p, handle, &snum)) {
5669 return WERR_BADFID;
5672 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5674 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5676 /* An error occured in print_job_start() so return an appropriate
5677 NT error code. */
5679 if (Printer->jobid == -1) {
5680 return map_werror_from_unix(errno);
5683 Printer->document_started=True;
5684 (*jobid) = Printer->jobid;
5686 return WERR_OK;
5689 /********************************************************************
5690 * api_spoolss_getprinter
5691 * called from the spoolss dispatcher
5693 ********************************************************************/
5695 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5697 POLICY_HND *handle = &q_u->handle;
5699 return _spoolss_enddocprinter_internal(p, handle);
5702 /****************************************************************************
5703 ****************************************************************************/
5705 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5707 POLICY_HND *handle = &q_u->handle;
5708 uint32 buffer_size = q_u->buffer_size;
5709 uint8 *buffer = q_u->buffer;
5710 uint32 *buffer_written = &q_u->buffer_size2;
5711 int snum;
5712 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5714 if (!Printer) {
5715 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5716 r_u->buffer_written = q_u->buffer_size2;
5717 return WERR_BADFID;
5720 if (!get_printer_snum(p, handle, &snum))
5721 return WERR_BADFID;
5723 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5724 (SMB_OFF_T)-1, (size_t)buffer_size);
5725 if (*buffer_written == (uint32)-1) {
5726 r_u->buffer_written = 0;
5727 if (errno == ENOSPC)
5728 return WERR_NO_SPOOL_SPACE;
5729 else
5730 return WERR_ACCESS_DENIED;
5733 r_u->buffer_written = q_u->buffer_size2;
5735 return WERR_OK;
5738 /********************************************************************
5739 * api_spoolss_getprinter
5740 * called from the spoolss dispatcher
5742 ********************************************************************/
5744 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5745 pipes_struct *p)
5747 struct current_user user;
5748 int snum;
5749 WERROR errcode = WERR_BADFUNC;
5750 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5752 get_current_user(&user, p);
5754 if (!Printer) {
5755 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5756 return WERR_BADFID;
5759 if (!get_printer_snum(p, handle, &snum))
5760 return WERR_BADFID;
5762 switch (command) {
5763 case PRINTER_CONTROL_PAUSE:
5764 if (print_queue_pause(&user, snum, &errcode)) {
5765 errcode = WERR_OK;
5767 break;
5768 case PRINTER_CONTROL_RESUME:
5769 case PRINTER_CONTROL_UNPAUSE:
5770 if (print_queue_resume(&user, snum, &errcode)) {
5771 errcode = WERR_OK;
5773 break;
5774 case PRINTER_CONTROL_PURGE:
5775 if (print_queue_purge(&user, snum, &errcode)) {
5776 errcode = WERR_OK;
5778 break;
5779 default:
5780 return WERR_UNKNOWN_LEVEL;
5783 return errcode;
5786 /********************************************************************
5787 * api_spoolss_abortprinter
5788 * From MSDN: "Deletes printer's spool file if printer is configured
5789 * for spooling"
5790 ********************************************************************/
5792 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5794 POLICY_HND *handle = &q_u->handle;
5795 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5796 int snum;
5797 struct current_user user;
5798 WERROR errcode = WERR_OK;
5800 if (!Printer) {
5801 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5802 return WERR_BADFID;
5805 if (!get_printer_snum(p, handle, &snum))
5806 return WERR_BADFID;
5808 get_current_user( &user, p );
5810 print_job_delete( &user, snum, Printer->jobid, &errcode );
5812 return errcode;
5815 /********************************************************************
5816 * called by spoolss_api_setprinter
5817 * when updating a printer description
5818 ********************************************************************/
5820 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5821 const SPOOL_PRINTER_INFO_LEVEL *info,
5822 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5824 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5825 WERROR result;
5826 int snum;
5828 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5830 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5831 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5832 OUR_HANDLE(handle)));
5834 result = WERR_BADFID;
5835 goto done;
5838 /* Check the user has permissions to change the security
5839 descriptor. By experimentation with two NT machines, the user
5840 requires Full Access to the printer to change security
5841 information. */
5843 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5844 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5845 result = WERR_ACCESS_DENIED;
5846 goto done;
5849 /* NT seems to like setting the security descriptor even though
5850 nothing may have actually changed. */
5852 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5854 if (DEBUGLEVEL >= 10) {
5855 SEC_ACL *the_acl;
5856 int i;
5858 the_acl = old_secdesc_ctr->sec->dacl;
5859 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5860 PRINTERNAME(snum), the_acl->num_aces));
5862 for (i = 0; i < the_acl->num_aces; i++) {
5863 fstring sid_str;
5865 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5867 DEBUG(10, ("%s 0x%08x\n", sid_str,
5868 the_acl->ace[i].info.mask));
5871 the_acl = secdesc_ctr->sec->dacl;
5873 if (the_acl) {
5874 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5875 PRINTERNAME(snum), the_acl->num_aces));
5877 for (i = 0; i < the_acl->num_aces; i++) {
5878 fstring sid_str;
5880 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5882 DEBUG(10, ("%s 0x%08x\n", sid_str,
5883 the_acl->ace[i].info.mask));
5885 } else {
5886 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5890 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5892 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5893 result = WERR_OK;
5894 goto done;
5897 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5899 done:
5901 return result;
5904 /********************************************************************
5905 Canonicalize printer info from a client
5907 ATTN: It does not matter what we set the servername to hear
5908 since we do the necessary work in get_a_printer() to set it to
5909 the correct value based on what the client sent in the
5910 _spoolss_open_printer_ex().
5911 ********************************************************************/
5913 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5915 fstring printername;
5916 const char *p;
5918 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5919 "portname=%s drivername=%s comment=%s location=%s\n",
5920 info->servername, info->printername, info->sharename,
5921 info->portname, info->drivername, info->comment, info->location));
5923 /* we force some elements to "correct" values */
5924 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5925 fstrcpy(info->sharename, lp_servicename(snum));
5927 /* check to see if we allow printername != sharename */
5929 if ( lp_force_printername(snum) ) {
5930 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5931 global_myname(), info->sharename );
5932 } else {
5934 /* make sure printername is in \\server\printername format */
5936 fstrcpy( printername, info->printername );
5937 p = printername;
5938 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5939 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5940 p++;
5943 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5944 global_myname(), p );
5947 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5948 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5952 return True;
5955 /****************************************************************************
5956 ****************************************************************************/
5958 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5960 char *cmd = lp_addport_cmd();
5961 pstring command;
5962 int ret;
5963 int fd;
5964 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5965 BOOL is_print_op = False;
5967 if ( !*cmd ) {
5968 return WERR_ACCESS_DENIED;
5971 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5973 if ( token )
5974 is_print_op = user_has_privileges( token, &se_printop );
5976 DEBUG(10,("Running [%s]\n", command));
5978 /********* BEGIN SePrintOperatorPrivilege **********/
5980 if ( is_print_op )
5981 become_root();
5983 ret = smbrun(command, &fd);
5985 if ( is_print_op )
5986 unbecome_root();
5988 /********* END SePrintOperatorPrivilege **********/
5990 DEBUGADD(10,("returned [%d]\n", ret));
5992 if ( ret != 0 ) {
5993 if (fd != -1)
5994 close(fd);
5995 return WERR_ACCESS_DENIED;
5998 return WERR_OK;
6001 /****************************************************************************
6002 ****************************************************************************/
6004 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6006 char *cmd = lp_addprinter_cmd();
6007 char **qlines;
6008 pstring command;
6009 int numlines;
6010 int ret;
6011 int fd;
6012 fstring remote_machine = "%m";
6013 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6014 BOOL is_print_op = False;
6016 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6018 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6019 cmd, printer->info_2->printername, printer->info_2->sharename,
6020 printer->info_2->portname, printer->info_2->drivername,
6021 printer->info_2->location, printer->info_2->comment, remote_machine);
6023 if ( token )
6024 is_print_op = user_has_privileges( token, &se_printop );
6026 DEBUG(10,("Running [%s]\n", command));
6028 /********* BEGIN SePrintOperatorPrivilege **********/
6030 if ( is_print_op )
6031 become_root();
6033 if ( (ret = smbrun(command, &fd)) == 0 ) {
6034 /* Tell everyone we updated smb.conf. */
6035 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6038 if ( is_print_op )
6039 unbecome_root();
6041 /********* END SePrintOperatorPrivilege **********/
6043 DEBUGADD(10,("returned [%d]\n", ret));
6045 if ( ret != 0 ) {
6046 if (fd != -1)
6047 close(fd);
6048 return False;
6051 /* reload our services immediately */
6052 reload_services( False );
6054 numlines = 0;
6055 /* Get lines and convert them back to dos-codepage */
6056 qlines = fd_lines_load(fd, &numlines, 0);
6057 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6058 close(fd);
6060 /* Set the portname to what the script says the portname should be. */
6061 /* but don't require anything to be return from the script exit a good error code */
6063 if (numlines) {
6064 /* Set the portname to what the script says the portname should be. */
6065 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6066 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6069 file_lines_free(qlines);
6070 return True;
6074 /********************************************************************
6075 * Called by spoolss_api_setprinter
6076 * when updating a printer description.
6077 ********************************************************************/
6079 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6080 const SPOOL_PRINTER_INFO_LEVEL *info,
6081 DEVICEMODE *devmode)
6083 int snum;
6084 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6085 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6086 WERROR result;
6087 UNISTR2 buffer;
6088 fstring asc_buffer;
6090 DEBUG(8,("update_printer\n"));
6092 result = WERR_OK;
6094 if (!Printer) {
6095 result = WERR_BADFID;
6096 goto done;
6099 if (!get_printer_snum(p, handle, &snum)) {
6100 result = WERR_BADFID;
6101 goto done;
6104 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6105 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6106 result = WERR_BADFID;
6107 goto done;
6110 DEBUGADD(8,("Converting info_2 struct\n"));
6113 * convert_printer_info converts the incoming
6114 * info from the client and overwrites the info
6115 * just read from the tdb in the pointer 'printer'.
6118 if (!convert_printer_info(info, printer, level)) {
6119 result = WERR_NOMEM;
6120 goto done;
6123 if (devmode) {
6124 /* we have a valid devmode
6125 convert it and link it*/
6127 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6128 if (!convert_devicemode(printer->info_2->printername, devmode,
6129 &printer->info_2->devmode)) {
6130 result = WERR_NOMEM;
6131 goto done;
6135 /* Do sanity check on the requested changes for Samba */
6137 if (!check_printer_ok(printer->info_2, snum)) {
6138 result = WERR_INVALID_PARAM;
6139 goto done;
6142 /* FIXME!!! If the driver has changed we really should verify that
6143 it is installed before doing much else --jerry */
6145 /* Check calling user has permission to update printer description */
6147 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6148 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6149 result = WERR_ACCESS_DENIED;
6150 goto done;
6153 /* Call addprinter hook */
6154 /* Check changes to see if this is really needed */
6156 if ( *lp_addprinter_cmd()
6157 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6158 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6159 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6160 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6162 /* add_printer_hook() will call reload_services() */
6164 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6165 result = WERR_ACCESS_DENIED;
6166 goto done;
6171 * When a *new* driver is bound to a printer, the drivername is used to
6172 * lookup previously saved driver initialization info, which is then
6173 * bound to the printer, simulating what happens in the Windows arch.
6175 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6177 if (!set_driver_init(printer, 2))
6179 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6180 printer->info_2->drivername));
6183 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6184 printer->info_2->drivername));
6186 notify_printer_driver(snum, printer->info_2->drivername);
6190 * flag which changes actually occured. This is a small subset of
6191 * all the possible changes. We also have to update things in the
6192 * DsSpooler key.
6195 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6196 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6197 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6198 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6200 notify_printer_comment(snum, printer->info_2->comment);
6203 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6204 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6205 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6206 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6208 notify_printer_sharename(snum, printer->info_2->sharename);
6211 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6212 char *pname;
6214 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6215 pname++;
6216 else
6217 pname = printer->info_2->printername;
6220 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6221 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6222 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6224 notify_printer_printername( snum, pname );
6227 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6228 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6229 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6230 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6232 notify_printer_port(snum, printer->info_2->portname);
6235 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6236 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6237 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6238 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6240 notify_printer_location(snum, printer->info_2->location);
6243 /* here we need to update some more DsSpooler keys */
6244 /* uNCName, serverName, shortServerName */
6246 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6247 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6248 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6249 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6250 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6252 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6253 global_myname(), printer->info_2->sharename );
6254 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6255 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6256 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6258 /* Update printer info */
6259 result = mod_a_printer(printer, 2);
6261 done:
6262 free_a_printer(&printer, 2);
6263 free_a_printer(&old_printer, 2);
6266 return result;
6269 /****************************************************************************
6270 ****************************************************************************/
6271 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6272 const SPOOL_PRINTER_INFO_LEVEL *info)
6274 #ifdef HAVE_ADS
6275 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6276 int snum;
6277 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6279 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6281 if (!Printer)
6282 return WERR_BADFID;
6284 if (!get_printer_snum(p, handle, &snum))
6285 return WERR_BADFID;
6287 nt_printer_publish(Printer, snum, info7->action);
6289 return WERR_OK;
6290 #else
6291 return WERR_UNKNOWN_LEVEL;
6292 #endif
6294 /****************************************************************************
6295 ****************************************************************************/
6297 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6299 POLICY_HND *handle = &q_u->handle;
6300 uint32 level = q_u->level;
6301 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6302 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6303 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6304 uint32 command = q_u->command;
6305 WERROR result;
6307 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6309 if (!Printer) {
6310 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6311 return WERR_BADFID;
6314 /* check the level */
6315 switch (level) {
6316 case 0:
6317 return control_printer(handle, command, p);
6318 case 2:
6319 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6320 if (!W_ERROR_IS_OK(result))
6321 return result;
6322 if (secdesc_ctr)
6323 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6324 return result;
6325 case 3:
6326 return update_printer_sec(handle, level, info, p,
6327 secdesc_ctr);
6328 case 7:
6329 return publish_or_unpublish_printer(p, handle, info);
6330 default:
6331 return WERR_UNKNOWN_LEVEL;
6335 /****************************************************************************
6336 ****************************************************************************/
6338 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6340 POLICY_HND *handle = &q_u->handle;
6341 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6343 if (!Printer) {
6344 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6345 return WERR_BADFID;
6348 if (Printer->notify.client_connected==True) {
6349 int snum = -1;
6351 if ( Printer->printer_type == SPLHND_SERVER)
6352 snum = -1;
6353 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6354 !get_printer_snum(p, handle, &snum) )
6355 return WERR_BADFID;
6357 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6360 Printer->notify.flags=0;
6361 Printer->notify.options=0;
6362 Printer->notify.localmachine[0]='\0';
6363 Printer->notify.printerlocal=0;
6364 if (Printer->notify.option)
6365 free_spool_notify_option(&Printer->notify.option);
6366 Printer->notify.client_connected=False;
6368 return WERR_OK;
6371 /****************************************************************************
6372 ****************************************************************************/
6374 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6376 /* that's an [in out] buffer */
6378 if (!q_u->buffer) {
6379 return WERR_INVALID_PARAM;
6382 rpcbuf_move(q_u->buffer, &r_u->buffer);
6384 r_u->needed = 0;
6385 return WERR_INVALID_PARAM; /* this is what a NT server
6386 returns for AddJob. AddJob
6387 must fail on non-local
6388 printers */
6391 /****************************************************************************
6392 ****************************************************************************/
6394 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6395 int position, int snum,
6396 NT_PRINTER_INFO_LEVEL *ntprinter)
6398 struct tm *t;
6400 t=gmtime(&queue->time);
6402 job_info->jobid=queue->job;
6403 init_unistr(&job_info->printername, lp_servicename(snum));
6404 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6405 init_unistr(&job_info->username, queue->fs_user);
6406 init_unistr(&job_info->document, queue->fs_file);
6407 init_unistr(&job_info->datatype, "RAW");
6408 init_unistr(&job_info->text_status, "");
6409 job_info->status=nt_printj_status(queue->status);
6410 job_info->priority=queue->priority;
6411 job_info->position=position;
6412 job_info->totalpages=queue->page_count;
6413 job_info->pagesprinted=0;
6415 make_systemtime(&job_info->submitted, t);
6418 /****************************************************************************
6419 ****************************************************************************/
6421 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6422 int position, int snum,
6423 NT_PRINTER_INFO_LEVEL *ntprinter,
6424 DEVICEMODE *devmode)
6426 struct tm *t;
6428 t=gmtime(&queue->time);
6430 job_info->jobid=queue->job;
6432 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6434 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6435 init_unistr(&job_info->username, queue->fs_user);
6436 init_unistr(&job_info->document, queue->fs_file);
6437 init_unistr(&job_info->notifyname, queue->fs_user);
6438 init_unistr(&job_info->datatype, "RAW");
6439 init_unistr(&job_info->printprocessor, "winprint");
6440 init_unistr(&job_info->parameters, "");
6441 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6442 init_unistr(&job_info->text_status, "");
6444 /* and here the security descriptor */
6446 job_info->status=nt_printj_status(queue->status);
6447 job_info->priority=queue->priority;
6448 job_info->position=position;
6449 job_info->starttime=0;
6450 job_info->untiltime=0;
6451 job_info->totalpages=queue->page_count;
6452 job_info->size=queue->size;
6453 make_systemtime(&(job_info->submitted), t);
6454 job_info->timeelapsed=0;
6455 job_info->pagesprinted=0;
6457 job_info->devmode = devmode;
6459 return (True);
6462 /****************************************************************************
6463 Enumjobs at level 1.
6464 ****************************************************************************/
6466 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6467 NT_PRINTER_INFO_LEVEL *ntprinter,
6468 RPC_BUFFER *buffer, uint32 offered,
6469 uint32 *needed, uint32 *returned)
6471 JOB_INFO_1 *info;
6472 int i;
6473 WERROR result = WERR_OK;
6475 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6476 if (info==NULL) {
6477 SAFE_FREE(queue);
6478 *returned=0;
6479 return WERR_NOMEM;
6482 for (i=0; i<*returned; i++)
6483 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6485 SAFE_FREE(queue);
6487 /* check the required size. */
6488 for (i=0; i<*returned; i++)
6489 (*needed) += spoolss_size_job_info_1(&info[i]);
6491 if (*needed > offered) {
6492 result = WERR_INSUFFICIENT_BUFFER;
6493 goto out;
6496 if (!rpcbuf_alloc_size(buffer, *needed)) {
6497 result = WERR_NOMEM;
6498 goto out;
6501 /* fill the buffer with the structures */
6502 for (i=0; i<*returned; i++)
6503 smb_io_job_info_1("", buffer, &info[i], 0);
6505 out:
6506 /* clear memory */
6507 SAFE_FREE(info);
6509 if ( !W_ERROR_IS_OK(result) )
6510 *returned = 0;
6512 return result;
6515 /****************************************************************************
6516 Enumjobs at level 2.
6517 ****************************************************************************/
6519 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6520 NT_PRINTER_INFO_LEVEL *ntprinter,
6521 RPC_BUFFER *buffer, uint32 offered,
6522 uint32 *needed, uint32 *returned)
6524 JOB_INFO_2 *info = NULL;
6525 int i;
6526 WERROR result = WERR_OK;
6527 DEVICEMODE *devmode = NULL;
6529 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6530 *returned=0;
6531 return WERR_NOMEM;
6534 /* this should not be a failure condition if the devmode is NULL */
6536 devmode = construct_dev_mode(snum);
6538 for (i=0; i<*returned; i++)
6539 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6541 free_a_printer(&ntprinter, 2);
6542 SAFE_FREE(queue);
6544 /* check the required size. */
6545 for (i=0; i<*returned; i++)
6546 (*needed) += spoolss_size_job_info_2(&info[i]);
6548 if (*needed > offered) {
6549 result = WERR_INSUFFICIENT_BUFFER;
6550 goto out;
6553 if (!rpcbuf_alloc_size(buffer, *needed)) {
6554 result = WERR_NOMEM;
6555 goto out;
6558 /* fill the buffer with the structures */
6559 for (i=0; i<*returned; i++)
6560 smb_io_job_info_2("", buffer, &info[i], 0);
6562 out:
6563 free_devmode(devmode);
6564 SAFE_FREE(info);
6566 if ( !W_ERROR_IS_OK(result) )
6567 *returned = 0;
6569 return result;
6573 /****************************************************************************
6574 Enumjobs.
6575 ****************************************************************************/
6577 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6579 POLICY_HND *handle = &q_u->handle;
6580 uint32 level = q_u->level;
6581 RPC_BUFFER *buffer = NULL;
6582 uint32 offered = q_u->offered;
6583 uint32 *needed = &r_u->needed;
6584 uint32 *returned = &r_u->returned;
6585 WERROR wret;
6586 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6587 int snum;
6588 print_status_struct prt_status;
6589 print_queue_struct *queue=NULL;
6591 /* that's an [in out] buffer */
6593 if (!q_u->buffer) {
6594 return WERR_INVALID_PARAM;
6597 rpcbuf_move(q_u->buffer, &r_u->buffer);
6598 buffer = r_u->buffer;
6600 DEBUG(4,("_spoolss_enumjobs\n"));
6602 *needed=0;
6603 *returned=0;
6605 /* lookup the printer snum and tdb entry */
6607 if (!get_printer_snum(p, handle, &snum))
6608 return WERR_BADFID;
6610 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6611 if ( !W_ERROR_IS_OK(wret) )
6612 return wret;
6614 *returned = print_queue_status(snum, &queue, &prt_status);
6615 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6617 if (*returned == 0) {
6618 SAFE_FREE(queue);
6619 return WERR_OK;
6622 switch (level) {
6623 case 1:
6624 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6625 return wret;
6626 case 2:
6627 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6628 return wret;
6629 default:
6630 SAFE_FREE(queue);
6631 *returned=0;
6632 wret = WERR_UNKNOWN_LEVEL;
6635 free_a_printer( &ntprinter, 2 );
6636 return wret;
6639 /****************************************************************************
6640 ****************************************************************************/
6642 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6644 return WERR_OK;
6647 /****************************************************************************
6648 ****************************************************************************/
6650 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6652 POLICY_HND *handle = &q_u->handle;
6653 uint32 jobid = q_u->jobid;
6654 uint32 command = q_u->command;
6656 struct current_user user;
6657 int snum;
6658 WERROR errcode = WERR_BADFUNC;
6660 if (!get_printer_snum(p, handle, &snum)) {
6661 return WERR_BADFID;
6664 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6665 return WERR_INVALID_PRINTER_NAME;
6668 get_current_user(&user, p);
6670 switch (command) {
6671 case JOB_CONTROL_CANCEL:
6672 case JOB_CONTROL_DELETE:
6673 if (print_job_delete(&user, snum, jobid, &errcode)) {
6674 errcode = WERR_OK;
6676 break;
6677 case JOB_CONTROL_PAUSE:
6678 if (print_job_pause(&user, snum, jobid, &errcode)) {
6679 errcode = WERR_OK;
6681 break;
6682 case JOB_CONTROL_RESTART:
6683 case JOB_CONTROL_RESUME:
6684 if (print_job_resume(&user, snum, jobid, &errcode)) {
6685 errcode = WERR_OK;
6687 break;
6688 default:
6689 return WERR_UNKNOWN_LEVEL;
6692 return errcode;
6695 /****************************************************************************
6696 Enumerates all printer drivers at level 1.
6697 ****************************************************************************/
6699 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6701 int i;
6702 int ndrivers;
6703 uint32 version;
6704 fstring *list = NULL;
6705 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6706 DRIVER_INFO_1 *driver_info_1=NULL;
6707 WERROR result = WERR_OK;
6709 *returned=0;
6711 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6712 list=NULL;
6713 ndrivers=get_ntdrivers(&list, architecture, version);
6714 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6716 if(ndrivers == -1)
6717 return WERR_NOMEM;
6719 if(ndrivers != 0) {
6720 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6721 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6722 SAFE_FREE(list);
6723 return WERR_NOMEM;
6727 for (i=0; i<ndrivers; i++) {
6728 WERROR status;
6729 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6730 ZERO_STRUCT(driver);
6731 status = get_a_printer_driver(&driver, 3, list[i],
6732 architecture, version);
6733 if (!W_ERROR_IS_OK(status)) {
6734 SAFE_FREE(list);
6735 return status;
6737 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6738 free_a_printer_driver(driver, 3);
6741 *returned+=ndrivers;
6742 SAFE_FREE(list);
6745 /* check the required size. */
6746 for (i=0; i<*returned; i++) {
6747 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6748 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6751 if (*needed > offered) {
6752 result = WERR_INSUFFICIENT_BUFFER;
6753 goto out;
6756 if (!rpcbuf_alloc_size(buffer, *needed)) {
6757 result = WERR_NOMEM;
6758 goto out;
6761 /* fill the buffer with the driver structures */
6762 for (i=0; i<*returned; i++) {
6763 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6764 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6767 out:
6768 SAFE_FREE(driver_info_1);
6770 if ( !W_ERROR_IS_OK(result) )
6771 *returned = 0;
6773 return result;
6776 /****************************************************************************
6777 Enumerates all printer drivers at level 2.
6778 ****************************************************************************/
6780 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6782 int i;
6783 int ndrivers;
6784 uint32 version;
6785 fstring *list = NULL;
6786 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6787 DRIVER_INFO_2 *driver_info_2=NULL;
6788 WERROR result = WERR_OK;
6790 *returned=0;
6792 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6793 list=NULL;
6794 ndrivers=get_ntdrivers(&list, architecture, version);
6795 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6797 if(ndrivers == -1)
6798 return WERR_NOMEM;
6800 if(ndrivers != 0) {
6801 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6802 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6803 SAFE_FREE(list);
6804 return WERR_NOMEM;
6808 for (i=0; i<ndrivers; i++) {
6809 WERROR status;
6811 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6812 ZERO_STRUCT(driver);
6813 status = get_a_printer_driver(&driver, 3, list[i],
6814 architecture, version);
6815 if (!W_ERROR_IS_OK(status)) {
6816 SAFE_FREE(list);
6817 return status;
6819 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6820 free_a_printer_driver(driver, 3);
6823 *returned+=ndrivers;
6824 SAFE_FREE(list);
6827 /* check the required size. */
6828 for (i=0; i<*returned; i++) {
6829 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6830 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6833 if (*needed > offered) {
6834 result = WERR_INSUFFICIENT_BUFFER;
6835 goto out;
6838 if (!rpcbuf_alloc_size(buffer, *needed)) {
6839 result = WERR_NOMEM;
6840 goto out;
6843 /* fill the buffer with the form structures */
6844 for (i=0; i<*returned; i++) {
6845 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6846 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6849 out:
6850 SAFE_FREE(driver_info_2);
6852 if ( !W_ERROR_IS_OK(result) )
6853 *returned = 0;
6855 return result;
6858 /****************************************************************************
6859 Enumerates all printer drivers at level 3.
6860 ****************************************************************************/
6862 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6864 int i;
6865 int ndrivers;
6866 uint32 version;
6867 fstring *list = NULL;
6868 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6869 DRIVER_INFO_3 *driver_info_3=NULL;
6870 WERROR result = WERR_OK;
6872 *returned=0;
6874 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6875 list=NULL;
6876 ndrivers=get_ntdrivers(&list, architecture, version);
6877 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6879 if(ndrivers == -1)
6880 return WERR_NOMEM;
6882 if(ndrivers != 0) {
6883 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6884 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6885 SAFE_FREE(list);
6886 return WERR_NOMEM;
6890 for (i=0; i<ndrivers; i++) {
6891 WERROR status;
6893 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6894 ZERO_STRUCT(driver);
6895 status = get_a_printer_driver(&driver, 3, list[i],
6896 architecture, version);
6897 if (!W_ERROR_IS_OK(status)) {
6898 SAFE_FREE(list);
6899 return status;
6901 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6902 free_a_printer_driver(driver, 3);
6905 *returned+=ndrivers;
6906 SAFE_FREE(list);
6909 /* check the required size. */
6910 for (i=0; i<*returned; i++) {
6911 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6912 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6915 if (*needed > offered) {
6916 result = WERR_INSUFFICIENT_BUFFER;
6917 goto out;
6920 if (!rpcbuf_alloc_size(buffer, *needed)) {
6921 result = WERR_NOMEM;
6922 goto out;
6925 /* fill the buffer with the driver structures */
6926 for (i=0; i<*returned; i++) {
6927 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6928 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6931 out:
6932 for (i=0; i<*returned; i++)
6933 SAFE_FREE(driver_info_3[i].dependentfiles);
6935 SAFE_FREE(driver_info_3);
6937 if ( !W_ERROR_IS_OK(result) )
6938 *returned = 0;
6940 return result;
6943 /****************************************************************************
6944 Enumerates all printer drivers.
6945 ****************************************************************************/
6947 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6949 uint32 level = q_u->level;
6950 RPC_BUFFER *buffer = NULL;
6951 uint32 offered = q_u->offered;
6952 uint32 *needed = &r_u->needed;
6953 uint32 *returned = &r_u->returned;
6955 fstring servername;
6956 fstring architecture;
6958 /* that's an [in out] buffer */
6960 if (!q_u->buffer) {
6961 return WERR_INVALID_PARAM;
6964 rpcbuf_move(q_u->buffer, &r_u->buffer);
6965 buffer = r_u->buffer;
6967 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6969 *needed = 0;
6970 *returned = 0;
6972 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6973 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6975 if ( !is_myname_or_ipaddr( servername ) )
6976 return WERR_UNKNOWN_PRINTER_DRIVER;
6978 switch (level) {
6979 case 1:
6980 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6981 case 2:
6982 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6983 case 3:
6984 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6985 default:
6986 return WERR_UNKNOWN_LEVEL;
6990 /****************************************************************************
6991 ****************************************************************************/
6993 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6995 form->flag=list->flag;
6996 init_unistr(&form->name, list->name);
6997 form->width=list->width;
6998 form->length=list->length;
6999 form->left=list->left;
7000 form->top=list->top;
7001 form->right=list->right;
7002 form->bottom=list->bottom;
7005 /****************************************************************************
7006 ****************************************************************************/
7008 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7010 uint32 level = q_u->level;
7011 RPC_BUFFER *buffer = NULL;
7012 uint32 offered = q_u->offered;
7013 uint32 *needed = &r_u->needed;
7014 uint32 *numofforms = &r_u->numofforms;
7015 uint32 numbuiltinforms;
7017 nt_forms_struct *list=NULL;
7018 nt_forms_struct *builtinlist=NULL;
7019 FORM_1 *forms_1;
7020 int buffer_size=0;
7021 int i;
7023 /* that's an [in out] buffer */
7025 if (!q_u->buffer) {
7026 return WERR_INVALID_PARAM;
7029 rpcbuf_move(q_u->buffer, &r_u->buffer);
7030 buffer = r_u->buffer;
7032 DEBUG(4,("_spoolss_enumforms\n"));
7033 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7034 DEBUGADD(5,("Info level [%d]\n", level));
7036 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7037 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7038 *numofforms = get_ntforms(&list);
7039 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7040 *numofforms += numbuiltinforms;
7042 if (*numofforms == 0)
7043 return WERR_NO_MORE_ITEMS;
7045 switch (level) {
7046 case 1:
7047 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7048 *numofforms=0;
7049 return WERR_NOMEM;
7052 /* construct the list of form structures */
7053 for (i=0; i<numbuiltinforms; i++) {
7054 DEBUGADD(6,("Filling form number [%d]\n",i));
7055 fill_form_1(&forms_1[i], &builtinlist[i]);
7058 SAFE_FREE(builtinlist);
7060 for (; i<*numofforms; i++) {
7061 DEBUGADD(6,("Filling form number [%d]\n",i));
7062 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7065 SAFE_FREE(list);
7067 /* check the required size. */
7068 for (i=0; i<numbuiltinforms; i++) {
7069 DEBUGADD(6,("adding form [%d]'s size\n",i));
7070 buffer_size += spoolss_size_form_1(&forms_1[i]);
7072 for (; i<*numofforms; i++) {
7073 DEBUGADD(6,("adding form [%d]'s size\n",i));
7074 buffer_size += spoolss_size_form_1(&forms_1[i]);
7077 *needed=buffer_size;
7079 if (*needed > offered) {
7080 SAFE_FREE(forms_1);
7081 *numofforms=0;
7082 return WERR_INSUFFICIENT_BUFFER;
7085 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7086 SAFE_FREE(forms_1);
7087 *numofforms=0;
7088 return WERR_NOMEM;
7091 /* fill the buffer with the form structures */
7092 for (i=0; i<numbuiltinforms; i++) {
7093 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7094 smb_io_form_1("", buffer, &forms_1[i], 0);
7096 for (; i<*numofforms; i++) {
7097 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7098 smb_io_form_1("", buffer, &forms_1[i], 0);
7101 SAFE_FREE(forms_1);
7103 return WERR_OK;
7105 default:
7106 SAFE_FREE(list);
7107 SAFE_FREE(builtinlist);
7108 return WERR_UNKNOWN_LEVEL;
7113 /****************************************************************************
7114 ****************************************************************************/
7116 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7118 uint32 level = q_u->level;
7119 UNISTR2 *uni_formname = &q_u->formname;
7120 RPC_BUFFER *buffer = NULL;
7121 uint32 offered = q_u->offered;
7122 uint32 *needed = &r_u->needed;
7124 nt_forms_struct *list=NULL;
7125 nt_forms_struct builtin_form;
7126 BOOL foundBuiltin;
7127 FORM_1 form_1;
7128 fstring form_name;
7129 int buffer_size=0;
7130 int numofforms=0, i=0;
7132 /* that's an [in out] buffer */
7134 if (!q_u->buffer) {
7135 return WERR_INVALID_PARAM;
7138 rpcbuf_move(q_u->buffer, &r_u->buffer);
7139 buffer = r_u->buffer;
7141 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7143 DEBUG(4,("_spoolss_getform\n"));
7144 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7145 DEBUGADD(5,("Info level [%d]\n", level));
7147 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7148 if (!foundBuiltin) {
7149 numofforms = get_ntforms(&list);
7150 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7152 if (numofforms == 0)
7153 return WERR_BADFID;
7156 switch (level) {
7157 case 1:
7158 if (foundBuiltin) {
7159 fill_form_1(&form_1, &builtin_form);
7160 } else {
7162 /* Check if the requested name is in the list of form structures */
7163 for (i=0; i<numofforms; i++) {
7165 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7167 if (strequal(form_name, list[i].name)) {
7168 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7169 fill_form_1(&form_1, &list[i]);
7170 break;
7174 SAFE_FREE(list);
7175 if (i == numofforms) {
7176 return WERR_BADFID;
7179 /* check the required size. */
7181 *needed=spoolss_size_form_1(&form_1);
7183 if (*needed > offered)
7184 return WERR_INSUFFICIENT_BUFFER;
7186 if (!rpcbuf_alloc_size(buffer, buffer_size))
7187 return WERR_NOMEM;
7189 /* fill the buffer with the form structures */
7190 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7191 smb_io_form_1("", buffer, &form_1, 0);
7193 return WERR_OK;
7195 default:
7196 SAFE_FREE(list);
7197 return WERR_UNKNOWN_LEVEL;
7201 /****************************************************************************
7202 ****************************************************************************/
7204 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7206 init_unistr(&port->port_name, name);
7209 /****************************************************************************
7210 TODO: This probably needs distinguish between TCP/IP and Local ports
7211 somehow.
7212 ****************************************************************************/
7214 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7216 init_unistr(&port->port_name, name);
7217 init_unistr(&port->monitor_name, "Local Monitor");
7218 init_unistr(&port->description, SPL_LOCAL_PORT );
7219 port->port_type=PORT_TYPE_WRITE;
7220 port->reserved=0x0;
7224 /****************************************************************************
7225 wrapper around the enumer ports command
7226 ****************************************************************************/
7228 WERROR enumports_hook( int *count, char ***lines )
7230 char *cmd = lp_enumports_cmd();
7231 char **qlines;
7232 pstring command;
7233 int numlines;
7234 int ret;
7235 int fd;
7238 /* if no hook then just fill in the default port */
7240 if ( !*cmd ) {
7241 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7242 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7243 qlines[1] = NULL;
7244 numlines = 1;
7246 else {
7247 /* we have a valid enumport command */
7249 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7251 DEBUG(10,("Running [%s]\n", command));
7252 ret = smbrun(command, &fd);
7253 DEBUG(10,("Returned [%d]\n", ret));
7254 if (ret != 0) {
7255 if (fd != -1)
7256 close(fd);
7258 return WERR_ACCESS_DENIED;
7261 numlines = 0;
7262 qlines = fd_lines_load(fd, &numlines, 0);
7263 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7264 close(fd);
7267 *count = numlines;
7268 *lines = qlines;
7270 return WERR_OK;
7273 /****************************************************************************
7274 enumports level 1.
7275 ****************************************************************************/
7277 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7279 PORT_INFO_1 *ports=NULL;
7280 int i=0;
7281 WERROR result = WERR_OK;
7282 char **qlines;
7283 int numlines;
7285 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7286 return result;
7288 if(numlines) {
7289 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7290 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7291 dos_errstr(WERR_NOMEM)));
7292 file_lines_free(qlines);
7293 return WERR_NOMEM;
7296 for (i=0; i<numlines; i++) {
7297 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7298 fill_port_1(&ports[i], qlines[i]);
7301 file_lines_free(qlines);
7304 *returned = numlines;
7306 /* check the required size. */
7307 for (i=0; i<*returned; i++) {
7308 DEBUGADD(6,("adding port [%d]'s size\n", i));
7309 *needed += spoolss_size_port_info_1(&ports[i]);
7312 if (*needed > offered) {
7313 result = WERR_INSUFFICIENT_BUFFER;
7314 goto out;
7317 if (!rpcbuf_alloc_size(buffer, *needed)) {
7318 result = WERR_NOMEM;
7319 goto out;
7322 /* fill the buffer with the ports structures */
7323 for (i=0; i<*returned; i++) {
7324 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7325 smb_io_port_1("", buffer, &ports[i], 0);
7328 out:
7329 SAFE_FREE(ports);
7331 if ( !W_ERROR_IS_OK(result) )
7332 *returned = 0;
7334 return result;
7337 /****************************************************************************
7338 enumports level 2.
7339 ****************************************************************************/
7341 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7343 PORT_INFO_2 *ports=NULL;
7344 int i=0;
7345 WERROR result = WERR_OK;
7346 char **qlines;
7347 int numlines;
7349 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7350 return result;
7353 if(numlines) {
7354 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7355 file_lines_free(qlines);
7356 return WERR_NOMEM;
7359 for (i=0; i<numlines; i++) {
7360 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7361 fill_port_2(&(ports[i]), qlines[i]);
7364 file_lines_free(qlines);
7367 *returned = numlines;
7369 /* check the required size. */
7370 for (i=0; i<*returned; i++) {
7371 DEBUGADD(6,("adding port [%d]'s size\n", i));
7372 *needed += spoolss_size_port_info_2(&ports[i]);
7375 if (*needed > offered) {
7376 result = WERR_INSUFFICIENT_BUFFER;
7377 goto out;
7380 if (!rpcbuf_alloc_size(buffer, *needed)) {
7381 result = WERR_NOMEM;
7382 goto out;
7385 /* fill the buffer with the ports structures */
7386 for (i=0; i<*returned; i++) {
7387 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7388 smb_io_port_2("", buffer, &ports[i], 0);
7391 out:
7392 SAFE_FREE(ports);
7394 if ( !W_ERROR_IS_OK(result) )
7395 *returned = 0;
7397 return result;
7400 /****************************************************************************
7401 enumports.
7402 ****************************************************************************/
7404 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7406 uint32 level = q_u->level;
7407 RPC_BUFFER *buffer = NULL;
7408 uint32 offered = q_u->offered;
7409 uint32 *needed = &r_u->needed;
7410 uint32 *returned = &r_u->returned;
7412 /* that's an [in out] buffer */
7414 if (!q_u->buffer) {
7415 return WERR_INVALID_PARAM;
7418 rpcbuf_move(q_u->buffer, &r_u->buffer);
7419 buffer = r_u->buffer;
7421 DEBUG(4,("_spoolss_enumports\n"));
7423 *returned=0;
7424 *needed=0;
7426 switch (level) {
7427 case 1:
7428 return enumports_level_1(buffer, offered, needed, returned);
7429 case 2:
7430 return enumports_level_2(buffer, offered, needed, returned);
7431 default:
7432 return WERR_UNKNOWN_LEVEL;
7436 /****************************************************************************
7437 ****************************************************************************/
7439 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7440 const SPOOL_PRINTER_INFO_LEVEL *info,
7441 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7442 uint32 user_switch, const SPOOL_USER_CTR *user,
7443 POLICY_HND *handle)
7445 NT_PRINTER_INFO_LEVEL *printer = NULL;
7446 fstring name;
7447 int snum;
7448 WERROR err = WERR_OK;
7450 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7451 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7452 return WERR_NOMEM;
7455 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7456 if (!convert_printer_info(info, printer, 2)) {
7457 free_a_printer(&printer, 2);
7458 return WERR_NOMEM;
7461 /* check to see if the printer already exists */
7463 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7464 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7465 printer->info_2->sharename));
7466 free_a_printer(&printer, 2);
7467 return WERR_PRINTER_ALREADY_EXISTS;
7470 /* FIXME!!! smbd should check to see if the driver is installed before
7471 trying to add a printer like this --jerry */
7473 if (*lp_addprinter_cmd() ) {
7474 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7475 free_a_printer(&printer,2);
7476 return WERR_ACCESS_DENIED;
7478 } else {
7479 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7480 "smb.conf parameter \"addprinter command\" is defined. This"
7481 "parameter must exist for this call to succeed\n",
7482 printer->info_2->sharename ));
7485 /* use our primary netbios name since get_a_printer() will convert
7486 it to what the client expects on a case by case basis */
7488 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7489 printer->info_2->sharename);
7492 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7493 free_a_printer(&printer,2);
7494 return WERR_ACCESS_DENIED;
7497 /* you must be a printer admin to add a new printer */
7498 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7499 free_a_printer(&printer,2);
7500 return WERR_ACCESS_DENIED;
7504 * Do sanity check on the requested changes for Samba.
7507 if (!check_printer_ok(printer->info_2, snum)) {
7508 free_a_printer(&printer,2);
7509 return WERR_INVALID_PARAM;
7513 * When a printer is created, the drivername bound to the printer is used
7514 * to lookup previously saved driver initialization info, which is then
7515 * bound to the new printer, simulating what happens in the Windows arch.
7518 if (!devmode)
7520 set_driver_init(printer, 2);
7522 else
7524 /* A valid devmode was included, convert and link it
7526 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7528 if (!convert_devicemode(printer->info_2->printername, devmode,
7529 &printer->info_2->devmode))
7530 return WERR_NOMEM;
7533 /* write the ASCII on disk */
7534 err = mod_a_printer(printer, 2);
7535 if (!W_ERROR_IS_OK(err)) {
7536 free_a_printer(&printer,2);
7537 return err;
7540 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7541 /* Handle open failed - remove addition. */
7542 del_a_printer(printer->info_2->sharename);
7543 free_a_printer(&printer,2);
7544 return WERR_ACCESS_DENIED;
7547 update_c_setprinter(False);
7548 free_a_printer(&printer,2);
7550 return WERR_OK;
7553 /****************************************************************************
7554 ****************************************************************************/
7556 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7558 UNISTR2 *uni_srv_name = q_u->server_name;
7559 uint32 level = q_u->level;
7560 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7561 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7562 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7563 uint32 user_switch = q_u->user_switch;
7564 SPOOL_USER_CTR *user = &q_u->user_ctr;
7565 POLICY_HND *handle = &r_u->handle;
7567 switch (level) {
7568 case 1:
7569 /* we don't handle yet */
7570 /* but I know what to do ... */
7571 return WERR_UNKNOWN_LEVEL;
7572 case 2:
7573 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7574 devmode, sdb,
7575 user_switch, user, handle);
7576 default:
7577 return WERR_UNKNOWN_LEVEL;
7581 /****************************************************************************
7582 ****************************************************************************/
7584 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7586 uint32 level = q_u->level;
7587 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7588 WERROR err = WERR_OK;
7589 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7590 struct current_user user;
7591 fstring driver_name;
7592 uint32 version;
7594 ZERO_STRUCT(driver);
7596 get_current_user(&user, p);
7598 if (!convert_printer_driver_info(info, &driver, level)) {
7599 err = WERR_NOMEM;
7600 goto done;
7603 DEBUG(5,("Cleaning driver's information\n"));
7604 err = clean_up_driver_struct(driver, level, &user);
7605 if (!W_ERROR_IS_OK(err))
7606 goto done;
7608 DEBUG(5,("Moving driver to final destination\n"));
7609 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7610 goto done;
7613 if (add_a_printer_driver(driver, level)!=0) {
7614 err = WERR_ACCESS_DENIED;
7615 goto done;
7618 /* BEGIN_ADMIN_LOG */
7619 switch(level) {
7620 case 3:
7621 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7622 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7623 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
7624 break;
7625 case 6:
7626 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7627 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7628 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
7629 break;
7631 /* END_ADMIN_LOG */
7634 * I think this is where he DrvUpgradePrinter() hook would be
7635 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7636 * server. Right now, we just need to send ourselves a message
7637 * to update each printer bound to this driver. --jerry
7640 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7641 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7642 driver_name));
7646 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7647 * decide if the driver init data should be deleted. The rules are:
7648 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7649 * 2) delete init data only if there is no 2k/Xp driver
7650 * 3) always delete init data
7651 * The generalized rule is always use init data from the highest order driver.
7652 * It is necessary to follow the driver install by an initialization step to
7653 * finish off this process.
7655 if (level == 3)
7656 version = driver.info_3->cversion;
7657 else if (level == 6)
7658 version = driver.info_6->version;
7659 else
7660 version = -1;
7661 switch (version) {
7663 * 9x printer driver - never delete init data
7665 case 0:
7666 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7667 driver_name));
7668 break;
7671 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7672 * there is no 2k/Xp driver init data for this driver name.
7674 case 2:
7676 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7678 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7680 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7682 if (!del_driver_init(driver_name))
7683 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7684 } else {
7686 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7688 free_a_printer_driver(driver1,3);
7689 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7690 driver_name));
7693 break;
7696 * 2k or Xp printer driver - always delete init data
7698 case 3:
7699 if (!del_driver_init(driver_name))
7700 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7701 break;
7703 default:
7704 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7705 break;
7709 done:
7710 free_a_printer_driver(driver, level);
7711 return err;
7714 /********************************************************************
7715 * spoolss_addprinterdriverex
7716 ********************************************************************/
7718 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7720 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7721 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7724 * we only support the semantics of AddPrinterDriver()
7725 * i.e. only copy files that are newer than existing ones
7728 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7729 return WERR_ACCESS_DENIED;
7731 ZERO_STRUCT(q_u_local);
7732 ZERO_STRUCT(r_u_local);
7734 /* just pass the information off to _spoolss_addprinterdriver() */
7735 q_u_local.server_name_ptr = q_u->server_name_ptr;
7736 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7737 q_u_local.level = q_u->level;
7738 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7740 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7743 /****************************************************************************
7744 ****************************************************************************/
7746 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7748 init_unistr(&info->name, name);
7751 /****************************************************************************
7752 ****************************************************************************/
7754 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7756 pstring path;
7757 pstring long_archi;
7758 fstring servername;
7759 char *pservername;
7760 const char *short_archi;
7761 DRIVER_DIRECTORY_1 *info=NULL;
7762 WERROR result = WERR_OK;
7764 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7765 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7767 /* check for beginning double '\'s and that the server
7768 long enough */
7770 pservername = servername;
7771 if ( *pservername == '\\' && strlen(servername)>2 ) {
7772 pservername += 2;
7775 if ( !is_myname_or_ipaddr( pservername ) )
7776 return WERR_INVALID_PARAM;
7778 if (!(short_archi = get_short_archi(long_archi)))
7779 return WERR_INVALID_ENVIRONMENT;
7781 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7782 return WERR_NOMEM;
7784 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7786 DEBUG(4,("printer driver directory: [%s]\n", path));
7788 fill_driverdir_1(info, path);
7790 *needed += spoolss_size_driverdir_info_1(info);
7792 if (*needed > offered) {
7793 result = WERR_INSUFFICIENT_BUFFER;
7794 goto out;
7797 if (!rpcbuf_alloc_size(buffer, *needed)) {
7798 result = WERR_NOMEM;
7799 goto out;
7802 smb_io_driverdir_1("", buffer, info, 0);
7804 out:
7805 SAFE_FREE(info);
7807 return result;
7810 /****************************************************************************
7811 ****************************************************************************/
7813 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7815 UNISTR2 *name = &q_u->name;
7816 UNISTR2 *uni_environment = &q_u->environment;
7817 uint32 level = q_u->level;
7818 RPC_BUFFER *buffer = NULL;
7819 uint32 offered = q_u->offered;
7820 uint32 *needed = &r_u->needed;
7822 /* that's an [in out] buffer */
7824 if (!q_u->buffer ) {
7825 return WERR_INVALID_PARAM;
7828 rpcbuf_move(q_u->buffer, &r_u->buffer);
7829 buffer = r_u->buffer;
7831 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7833 *needed=0;
7835 switch(level) {
7836 case 1:
7837 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7838 default:
7839 return WERR_UNKNOWN_LEVEL;
7843 /****************************************************************************
7844 ****************************************************************************/
7846 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7848 POLICY_HND *handle = &q_u->handle;
7849 uint32 idx = q_u->index;
7850 uint32 in_value_len = q_u->valuesize;
7851 uint32 in_data_len = q_u->datasize;
7852 uint32 *out_max_value_len = &r_u->valuesize;
7853 uint16 **out_value = &r_u->value;
7854 uint32 *out_value_len = &r_u->realvaluesize;
7855 uint32 *out_type = &r_u->type;
7856 uint32 *out_max_data_len = &r_u->datasize;
7857 uint8 **data_out = &r_u->data;
7858 uint32 *out_data_len = &r_u->realdatasize;
7860 NT_PRINTER_INFO_LEVEL *printer = NULL;
7862 uint32 biggest_valuesize;
7863 uint32 biggest_datasize;
7864 uint32 data_len;
7865 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7866 int snum;
7867 WERROR result;
7868 REGISTRY_VALUE *val = NULL;
7869 NT_PRINTER_DATA *p_data;
7870 int i, key_index, num_values;
7871 int name_length;
7873 *out_type = 0;
7875 *out_max_data_len = 0;
7876 *data_out = NULL;
7877 *out_data_len = 0;
7879 DEBUG(5,("spoolss_enumprinterdata\n"));
7881 if (!Printer) {
7882 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7883 return WERR_BADFID;
7886 if (!get_printer_snum(p,handle, &snum))
7887 return WERR_BADFID;
7889 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7890 if (!W_ERROR_IS_OK(result))
7891 return result;
7893 p_data = printer->info_2->data;
7894 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7896 result = WERR_OK;
7899 * The NT machine wants to know the biggest size of value and data
7901 * cf: MSDN EnumPrinterData remark section
7904 if ( !in_value_len && !in_data_len && (key_index != -1) )
7906 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7908 biggest_valuesize = 0;
7909 biggest_datasize = 0;
7911 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7913 for ( i=0; i<num_values; i++ )
7915 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7917 name_length = strlen(val->valuename);
7918 if ( strlen(val->valuename) > biggest_valuesize )
7919 biggest_valuesize = name_length;
7921 if ( val->size > biggest_datasize )
7922 biggest_datasize = val->size;
7924 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7925 biggest_datasize));
7928 /* the value is an UNICODE string but real_value_size is the length
7929 in bytes including the trailing 0 */
7931 *out_value_len = 2 * (1+biggest_valuesize);
7932 *out_data_len = biggest_datasize;
7934 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7936 goto done;
7940 * the value len is wrong in NT sp3
7941 * that's the number of bytes not the number of unicode chars
7944 if ( key_index != -1 )
7945 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7947 if ( !val )
7950 /* out_value should default to "" or else NT4 has
7951 problems unmarshalling the response */
7953 *out_max_value_len=(in_value_len/sizeof(uint16));
7955 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7957 result = WERR_NOMEM;
7958 goto done;
7961 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7963 /* the data is counted in bytes */
7965 *out_max_data_len = in_data_len;
7966 *out_data_len = in_data_len;
7968 /* only allocate when given a non-zero data_len */
7970 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7972 result = WERR_NOMEM;
7973 goto done;
7976 result = WERR_NO_MORE_ITEMS;
7978 else
7981 * the value is:
7982 * - counted in bytes in the request
7983 * - counted in UNICODE chars in the max reply
7984 * - counted in bytes in the real size
7986 * take a pause *before* coding not *during* coding
7989 /* name */
7990 *out_max_value_len=(in_value_len/sizeof(uint16));
7991 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7993 result = WERR_NOMEM;
7994 goto done;
7997 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7999 /* type */
8001 *out_type = regval_type( val );
8003 /* data - counted in bytes */
8005 *out_max_data_len = in_data_len;
8006 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8008 result = WERR_NOMEM;
8009 goto done;
8011 data_len = regval_size(val);
8012 if ( *data_out )
8013 memcpy( *data_out, regval_data_p(val), data_len );
8014 *out_data_len = data_len;
8017 done:
8018 free_a_printer(&printer, 2);
8019 return result;
8022 /****************************************************************************
8023 ****************************************************************************/
8025 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8027 POLICY_HND *handle = &q_u->handle;
8028 UNISTR2 *value = &q_u->value;
8029 uint32 type = q_u->type;
8030 uint8 *data = q_u->data;
8031 uint32 real_len = q_u->real_len;
8033 NT_PRINTER_INFO_LEVEL *printer = NULL;
8034 int snum=0;
8035 WERROR status = WERR_OK;
8036 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8037 fstring valuename;
8039 DEBUG(5,("spoolss_setprinterdata\n"));
8041 if (!Printer) {
8042 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8043 return WERR_BADFID;
8046 if ( Printer->printer_type == SPLHND_SERVER ) {
8047 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8048 return WERR_INVALID_PARAM;
8051 if (!get_printer_snum(p,handle, &snum))
8052 return WERR_BADFID;
8055 * Access check : NT returns "access denied" if you make a
8056 * SetPrinterData call without the necessary privildge.
8057 * we were originally returning OK if nothing changed
8058 * which made Win2k issue **a lot** of SetPrinterData
8059 * when connecting to a printer --jerry
8062 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8064 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8065 status = WERR_ACCESS_DENIED;
8066 goto done;
8069 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8070 if (!W_ERROR_IS_OK(status))
8071 return status;
8073 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8076 * When client side code sets a magic printer data key, detect it and save
8077 * the current printer data and the magic key's data (its the DEVMODE) for
8078 * future printer/driver initializations.
8080 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8082 /* Set devmode and printer initialization info */
8083 status = save_driver_init( printer, 2, data, real_len );
8085 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8087 else
8089 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8090 type, data, real_len );
8091 if ( W_ERROR_IS_OK(status) )
8092 status = mod_a_printer(printer, 2);
8095 done:
8096 free_a_printer(&printer, 2);
8098 return status;
8101 /****************************************************************************
8102 ****************************************************************************/
8104 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8106 POLICY_HND *handle = &q_u->handle;
8107 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8108 int snum;
8110 DEBUG(5,("_spoolss_resetprinter\n"));
8113 * All we do is to check to see if the handle and queue is valid.
8114 * This call really doesn't mean anything to us because we only
8115 * support RAW printing. --jerry
8118 if (!Printer) {
8119 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8120 return WERR_BADFID;
8123 if (!get_printer_snum(p,handle, &snum))
8124 return WERR_BADFID;
8127 /* blindly return success */
8128 return WERR_OK;
8132 /****************************************************************************
8133 ****************************************************************************/
8135 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8137 POLICY_HND *handle = &q_u->handle;
8138 UNISTR2 *value = &q_u->valuename;
8140 NT_PRINTER_INFO_LEVEL *printer = NULL;
8141 int snum=0;
8142 WERROR status = WERR_OK;
8143 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8144 pstring valuename;
8146 DEBUG(5,("spoolss_deleteprinterdata\n"));
8148 if (!Printer) {
8149 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8150 return WERR_BADFID;
8153 if (!get_printer_snum(p, handle, &snum))
8154 return WERR_BADFID;
8156 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8157 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8158 return WERR_ACCESS_DENIED;
8161 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8162 if (!W_ERROR_IS_OK(status))
8163 return status;
8165 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8167 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8169 if ( W_ERROR_IS_OK(status) )
8170 mod_a_printer( printer, 2 );
8172 free_a_printer(&printer, 2);
8174 return status;
8177 /****************************************************************************
8178 ****************************************************************************/
8180 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8182 POLICY_HND *handle = &q_u->handle;
8183 FORM *form = &q_u->form;
8184 nt_forms_struct tmpForm;
8185 int snum;
8186 WERROR status = WERR_OK;
8187 NT_PRINTER_INFO_LEVEL *printer = NULL;
8189 int count=0;
8190 nt_forms_struct *list=NULL;
8191 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8193 DEBUG(5,("spoolss_addform\n"));
8195 if (!Printer) {
8196 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8197 return WERR_BADFID;
8201 /* forms can be added on printer of on the print server handle */
8203 if ( Printer->printer_type == SPLHND_PRINTER )
8205 if (!get_printer_snum(p,handle, &snum))
8206 return WERR_BADFID;
8208 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8209 if (!W_ERROR_IS_OK(status))
8210 goto done;
8213 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8214 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8215 status = WERR_ACCESS_DENIED;
8216 goto done;
8219 /* can't add if builtin */
8221 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8222 status = WERR_ALREADY_EXISTS;
8223 goto done;
8226 count = get_ntforms(&list);
8228 if(!add_a_form(&list, form, &count)) {
8229 status = WERR_NOMEM;
8230 goto done;
8233 write_ntforms(&list, count);
8236 * ChangeID must always be set if this is a printer
8239 if ( Printer->printer_type == SPLHND_PRINTER )
8240 status = mod_a_printer(printer, 2);
8242 done:
8243 if ( printer )
8244 free_a_printer(&printer, 2);
8245 SAFE_FREE(list);
8247 return status;
8250 /****************************************************************************
8251 ****************************************************************************/
8253 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8255 POLICY_HND *handle = &q_u->handle;
8256 UNISTR2 *form_name = &q_u->name;
8257 nt_forms_struct tmpForm;
8258 int count=0;
8259 nt_forms_struct *list=NULL;
8260 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8261 int snum;
8262 WERROR status = WERR_OK;
8263 NT_PRINTER_INFO_LEVEL *printer = NULL;
8265 DEBUG(5,("spoolss_deleteform\n"));
8267 if (!Printer) {
8268 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8269 return WERR_BADFID;
8272 /* forms can be deleted on printer of on the print server handle */
8274 if ( Printer->printer_type == SPLHND_PRINTER )
8276 if (!get_printer_snum(p,handle, &snum))
8277 return WERR_BADFID;
8279 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8280 if (!W_ERROR_IS_OK(status))
8281 goto done;
8284 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8285 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8286 status = WERR_ACCESS_DENIED;
8287 goto done;
8290 /* can't delete if builtin */
8292 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8293 status = WERR_INVALID_PARAM;
8294 goto done;
8297 count = get_ntforms(&list);
8299 if ( !delete_a_form(&list, form_name, &count, &status ))
8300 goto done;
8303 * ChangeID must always be set if this is a printer
8306 if ( Printer->printer_type == SPLHND_PRINTER )
8307 status = mod_a_printer(printer, 2);
8309 done:
8310 if ( printer )
8311 free_a_printer(&printer, 2);
8312 SAFE_FREE(list);
8314 return status;
8317 /****************************************************************************
8318 ****************************************************************************/
8320 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8322 POLICY_HND *handle = &q_u->handle;
8323 FORM *form = &q_u->form;
8324 nt_forms_struct tmpForm;
8325 int snum;
8326 WERROR status = WERR_OK;
8327 NT_PRINTER_INFO_LEVEL *printer = NULL;
8329 int count=0;
8330 nt_forms_struct *list=NULL;
8331 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8333 DEBUG(5,("spoolss_setform\n"));
8335 if (!Printer) {
8336 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8337 return WERR_BADFID;
8340 /* forms can be modified on printer of on the print server handle */
8342 if ( Printer->printer_type == SPLHND_PRINTER )
8344 if (!get_printer_snum(p,handle, &snum))
8345 return WERR_BADFID;
8347 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8348 if (!W_ERROR_IS_OK(status))
8349 goto done;
8352 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8353 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8354 status = WERR_ACCESS_DENIED;
8355 goto done;
8358 /* can't set if builtin */
8359 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8360 status = WERR_INVALID_PARAM;
8361 goto done;
8364 count = get_ntforms(&list);
8365 update_a_form(&list, form, count);
8366 write_ntforms(&list, count);
8369 * ChangeID must always be set if this is a printer
8372 if ( Printer->printer_type == SPLHND_PRINTER )
8373 status = mod_a_printer(printer, 2);
8376 done:
8377 if ( printer )
8378 free_a_printer(&printer, 2);
8379 SAFE_FREE(list);
8381 return status;
8384 /****************************************************************************
8385 enumprintprocessors level 1.
8386 ****************************************************************************/
8388 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8390 PRINTPROCESSOR_1 *info_1=NULL;
8391 WERROR result = WERR_OK;
8393 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8394 return WERR_NOMEM;
8396 (*returned) = 0x1;
8398 init_unistr(&info_1->name, "winprint");
8400 *needed += spoolss_size_printprocessor_info_1(info_1);
8402 if (*needed > offered) {
8403 result = WERR_INSUFFICIENT_BUFFER;
8404 goto out;
8407 if (!rpcbuf_alloc_size(buffer, *needed)) {
8408 result = WERR_NOMEM;
8409 goto out;
8412 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8414 out:
8415 SAFE_FREE(info_1);
8417 if ( !W_ERROR_IS_OK(result) )
8418 *returned = 0;
8420 return result;
8423 /****************************************************************************
8424 ****************************************************************************/
8426 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8428 uint32 level = q_u->level;
8429 RPC_BUFFER *buffer = NULL;
8430 uint32 offered = q_u->offered;
8431 uint32 *needed = &r_u->needed;
8432 uint32 *returned = &r_u->returned;
8434 /* that's an [in out] buffer */
8436 if (!q_u->buffer) {
8437 return WERR_INVALID_PARAM;
8440 rpcbuf_move(q_u->buffer, &r_u->buffer);
8441 buffer = r_u->buffer;
8443 DEBUG(5,("spoolss_enumprintprocessors\n"));
8446 * Enumerate the print processors ...
8448 * Just reply with "winprint", to keep NT happy
8449 * and I can use my nice printer checker.
8452 *returned=0;
8453 *needed=0;
8455 switch (level) {
8456 case 1:
8457 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8458 default:
8459 return WERR_UNKNOWN_LEVEL;
8463 /****************************************************************************
8464 enumprintprocdatatypes level 1.
8465 ****************************************************************************/
8467 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8469 PRINTPROCDATATYPE_1 *info_1=NULL;
8470 WERROR result = WERR_NOMEM;
8472 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8473 return WERR_NOMEM;
8475 (*returned) = 0x1;
8477 init_unistr(&info_1->name, "RAW");
8479 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8481 if (*needed > offered) {
8482 result = WERR_INSUFFICIENT_BUFFER;
8483 goto out;
8486 if (!rpcbuf_alloc_size(buffer, *needed)) {
8487 result = WERR_NOMEM;
8488 goto out;
8491 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8493 out:
8494 SAFE_FREE(info_1);
8496 if ( !W_ERROR_IS_OK(result) )
8497 *returned = 0;
8499 return result;
8502 /****************************************************************************
8503 ****************************************************************************/
8505 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8507 uint32 level = q_u->level;
8508 RPC_BUFFER *buffer = NULL;
8509 uint32 offered = q_u->offered;
8510 uint32 *needed = &r_u->needed;
8511 uint32 *returned = &r_u->returned;
8513 /* that's an [in out] buffer */
8515 if (!q_u->buffer) {
8516 return WERR_INVALID_PARAM;
8519 rpcbuf_move(q_u->buffer, &r_u->buffer);
8520 buffer = r_u->buffer;
8522 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8524 *returned=0;
8525 *needed=0;
8527 switch (level) {
8528 case 1:
8529 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8530 default:
8531 return WERR_UNKNOWN_LEVEL;
8535 /****************************************************************************
8536 enumprintmonitors level 1.
8537 ****************************************************************************/
8539 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8541 PRINTMONITOR_1 *info_1;
8542 WERROR result = WERR_OK;
8543 int i;
8545 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8546 return WERR_NOMEM;
8548 *returned = 2;
8550 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8551 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8553 for ( i=0; i<*returned; i++ ) {
8554 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8557 if (*needed > offered) {
8558 result = WERR_INSUFFICIENT_BUFFER;
8559 goto out;
8562 if (!rpcbuf_alloc_size(buffer, *needed)) {
8563 result = WERR_NOMEM;
8564 goto out;
8567 for ( i=0; i<*returned; i++ ) {
8568 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8571 out:
8572 SAFE_FREE(info_1);
8574 if ( !W_ERROR_IS_OK(result) )
8575 *returned = 0;
8577 return result;
8580 /****************************************************************************
8581 enumprintmonitors level 2.
8582 ****************************************************************************/
8584 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8586 PRINTMONITOR_2 *info_2;
8587 WERROR result = WERR_OK;
8588 int i;
8590 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8591 return WERR_NOMEM;
8593 *returned = 2;
8595 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8596 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8597 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8599 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8600 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8601 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8603 for ( i=0; i<*returned; i++ ) {
8604 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8607 if (*needed > offered) {
8608 result = WERR_INSUFFICIENT_BUFFER;
8609 goto out;
8612 if (!rpcbuf_alloc_size(buffer, *needed)) {
8613 result = WERR_NOMEM;
8614 goto out;
8617 for ( i=0; i<*returned; i++ ) {
8618 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8621 out:
8622 SAFE_FREE(info_2);
8624 if ( !W_ERROR_IS_OK(result) )
8625 *returned = 0;
8627 return result;
8630 /****************************************************************************
8631 ****************************************************************************/
8633 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8635 uint32 level = q_u->level;
8636 RPC_BUFFER *buffer = NULL;
8637 uint32 offered = q_u->offered;
8638 uint32 *needed = &r_u->needed;
8639 uint32 *returned = &r_u->returned;
8641 /* that's an [in out] buffer */
8643 if (!q_u->buffer) {
8644 return WERR_INVALID_PARAM;
8647 rpcbuf_move(q_u->buffer, &r_u->buffer);
8648 buffer = r_u->buffer;
8650 DEBUG(5,("spoolss_enumprintmonitors\n"));
8653 * Enumerate the print monitors ...
8655 * Just reply with "Local Port", to keep NT happy
8656 * and I can use my nice printer checker.
8659 *returned=0;
8660 *needed=0;
8662 switch (level) {
8663 case 1:
8664 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8665 case 2:
8666 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8667 default:
8668 return WERR_UNKNOWN_LEVEL;
8672 /****************************************************************************
8673 ****************************************************************************/
8675 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8676 NT_PRINTER_INFO_LEVEL *ntprinter,
8677 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8678 uint32 *needed)
8680 int i=0;
8681 BOOL found=False;
8682 JOB_INFO_1 *info_1=NULL;
8683 WERROR result = WERR_OK;
8685 info_1=SMB_MALLOC_P(JOB_INFO_1);
8687 if (info_1 == NULL) {
8688 return WERR_NOMEM;
8691 for (i=0; i<count && found==False; i++) {
8692 if ((*queue)[i].job==(int)jobid)
8693 found=True;
8696 if (found==False) {
8697 SAFE_FREE(info_1);
8698 /* NT treats not found as bad param... yet another bad choice */
8699 return WERR_INVALID_PARAM;
8702 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8704 *needed += spoolss_size_job_info_1(info_1);
8706 if (*needed > offered) {
8707 result = WERR_INSUFFICIENT_BUFFER;
8708 goto out;
8711 if (!rpcbuf_alloc_size(buffer, *needed)) {
8712 result = WERR_NOMEM;
8713 goto out;
8716 smb_io_job_info_1("", buffer, info_1, 0);
8718 out:
8719 SAFE_FREE(info_1);
8721 return result;
8724 /****************************************************************************
8725 ****************************************************************************/
8727 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8728 NT_PRINTER_INFO_LEVEL *ntprinter,
8729 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8730 uint32 *needed)
8732 int i = 0;
8733 BOOL found = False;
8734 JOB_INFO_2 *info_2;
8735 WERROR result;
8736 DEVICEMODE *devmode = NULL;
8737 NT_DEVICEMODE *nt_devmode = NULL;
8739 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8740 return WERR_NOMEM;
8742 ZERO_STRUCTP(info_2);
8744 for ( i=0; i<count && found==False; i++ )
8746 if ((*queue)[i].job == (int)jobid)
8747 found = True;
8750 if ( !found ) {
8751 /* NT treats not found as bad param... yet another bad
8752 choice */
8753 result = WERR_INVALID_PARAM;
8754 goto done;
8758 * if the print job does not have a DEVMODE associated with it,
8759 * just use the one for the printer. A NULL devicemode is not
8760 * a failure condition
8763 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8764 devmode = construct_dev_mode(snum);
8765 else {
8766 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8767 ZERO_STRUCTP( devmode );
8768 convert_nt_devicemode( devmode, nt_devmode );
8772 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8774 *needed += spoolss_size_job_info_2(info_2);
8776 if (*needed > offered) {
8777 result = WERR_INSUFFICIENT_BUFFER;
8778 goto done;
8781 if (!rpcbuf_alloc_size(buffer, *needed)) {
8782 result = WERR_NOMEM;
8783 goto done;
8786 smb_io_job_info_2("", buffer, info_2, 0);
8788 result = WERR_OK;
8790 done:
8791 /* Cleanup allocated memory */
8793 free_job_info_2(info_2); /* Also frees devmode */
8794 SAFE_FREE(info_2);
8796 return result;
8799 /****************************************************************************
8800 ****************************************************************************/
8802 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8804 POLICY_HND *handle = &q_u->handle;
8805 uint32 jobid = q_u->jobid;
8806 uint32 level = q_u->level;
8807 RPC_BUFFER *buffer = NULL;
8808 uint32 offered = q_u->offered;
8809 uint32 *needed = &r_u->needed;
8810 WERROR wstatus = WERR_OK;
8811 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8812 int snum;
8813 int count;
8814 print_queue_struct *queue = NULL;
8815 print_status_struct prt_status;
8817 /* that's an [in out] buffer */
8819 if (!q_u->buffer) {
8820 return WERR_INVALID_PARAM;
8823 rpcbuf_move(q_u->buffer, &r_u->buffer);
8824 buffer = r_u->buffer;
8826 DEBUG(5,("spoolss_getjob\n"));
8828 *needed = 0;
8830 if (!get_printer_snum(p, handle, &snum))
8831 return WERR_BADFID;
8833 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8834 if ( !W_ERROR_IS_OK(wstatus) )
8835 return wstatus;
8837 count = print_queue_status(snum, &queue, &prt_status);
8839 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8840 count, prt_status.status, prt_status.message));
8842 switch ( level ) {
8843 case 1:
8844 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8845 buffer, offered, needed);
8846 break;
8847 case 2:
8848 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8849 buffer, offered, needed);
8850 break;
8851 default:
8852 wstatus = WERR_UNKNOWN_LEVEL;
8853 break;
8856 SAFE_FREE(queue);
8857 free_a_printer( &ntprinter, 2 );
8859 return wstatus;
8862 /********************************************************************
8863 spoolss_getprinterdataex
8865 From MSDN documentation of GetPrinterDataEx: pass request
8866 to GetPrinterData if key is "PrinterDriverData".
8867 ********************************************************************/
8869 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8871 POLICY_HND *handle = &q_u->handle;
8872 uint32 in_size = q_u->size;
8873 uint32 *type = &r_u->type;
8874 uint32 *out_size = &r_u->size;
8875 uint8 **data = &r_u->data;
8876 uint32 *needed = &r_u->needed;
8877 fstring keyname, valuename;
8879 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8881 NT_PRINTER_INFO_LEVEL *printer = NULL;
8882 int snum = 0;
8883 WERROR status = WERR_OK;
8885 DEBUG(4,("_spoolss_getprinterdataex\n"));
8887 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8888 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8890 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8891 keyname, valuename));
8893 /* in case of problem, return some default values */
8895 *needed = 0;
8896 *type = 0;
8897 *out_size = in_size;
8899 if (!Printer) {
8900 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8901 status = WERR_BADFID;
8902 goto done;
8905 /* Is the handle to a printer or to the server? */
8907 if (Printer->printer_type == SPLHND_SERVER) {
8908 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8909 status = WERR_INVALID_PARAM;
8910 goto done;
8913 if ( !get_printer_snum(p,handle, &snum) )
8914 return WERR_BADFID;
8916 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8917 if ( !W_ERROR_IS_OK(status) )
8918 goto done;
8920 /* check to see if the keyname is valid */
8921 if ( !strlen(keyname) ) {
8922 status = WERR_INVALID_PARAM;
8923 goto done;
8926 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8927 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8928 free_a_printer( &printer, 2 );
8929 status = WERR_BADFILE;
8930 goto done;
8933 /* When given a new keyname, we should just create it */
8935 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8937 if (*needed > *out_size)
8938 status = WERR_MORE_DATA;
8940 done:
8941 if ( !W_ERROR_IS_OK(status) )
8943 DEBUG(5, ("error: allocating %d\n", *out_size));
8945 /* reply this param doesn't exist */
8947 if ( *out_size )
8949 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8950 status = WERR_NOMEM;
8951 goto done;
8954 else {
8955 *data = NULL;
8959 if ( printer )
8960 free_a_printer( &printer, 2 );
8962 return status;
8965 /********************************************************************
8966 * spoolss_setprinterdataex
8967 ********************************************************************/
8969 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8971 POLICY_HND *handle = &q_u->handle;
8972 uint32 type = q_u->type;
8973 uint8 *data = q_u->data;
8974 uint32 real_len = q_u->real_len;
8976 NT_PRINTER_INFO_LEVEL *printer = NULL;
8977 int snum = 0;
8978 WERROR status = WERR_OK;
8979 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8980 fstring valuename;
8981 fstring keyname;
8982 char *oid_string;
8984 DEBUG(4,("_spoolss_setprinterdataex\n"));
8986 /* From MSDN documentation of SetPrinterDataEx: pass request to
8987 SetPrinterData if key is "PrinterDriverData" */
8989 if (!Printer) {
8990 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8991 return WERR_BADFID;
8994 if ( Printer->printer_type == SPLHND_SERVER ) {
8995 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8996 return WERR_INVALID_PARAM;
8999 if ( !get_printer_snum(p,handle, &snum) )
9000 return WERR_BADFID;
9003 * Access check : NT returns "access denied" if you make a
9004 * SetPrinterData call without the necessary privildge.
9005 * we were originally returning OK if nothing changed
9006 * which made Win2k issue **a lot** of SetPrinterData
9007 * when connecting to a printer --jerry
9010 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9012 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9013 return WERR_ACCESS_DENIED;
9016 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9017 if (!W_ERROR_IS_OK(status))
9018 return status;
9020 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9021 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9023 /* check for OID in valuename */
9025 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9027 *oid_string = '\0';
9028 oid_string++;
9031 /* save the registry data */
9033 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9035 if ( W_ERROR_IS_OK(status) )
9037 /* save the OID if one was specified */
9038 if ( oid_string ) {
9039 fstrcat( keyname, "\\" );
9040 fstrcat( keyname, SPOOL_OID_KEY );
9043 * I'm not checking the status here on purpose. Don't know
9044 * if this is right, but I'm returning the status from the
9045 * previous set_printer_dataex() call. I have no idea if
9046 * this is right. --jerry
9049 set_printer_dataex( printer, keyname, valuename,
9050 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9053 status = mod_a_printer(printer, 2);
9056 free_a_printer(&printer, 2);
9058 return status;
9062 /********************************************************************
9063 * spoolss_deleteprinterdataex
9064 ********************************************************************/
9066 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9068 POLICY_HND *handle = &q_u->handle;
9069 UNISTR2 *value = &q_u->valuename;
9070 UNISTR2 *key = &q_u->keyname;
9072 NT_PRINTER_INFO_LEVEL *printer = NULL;
9073 int snum=0;
9074 WERROR status = WERR_OK;
9075 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9076 pstring valuename, keyname;
9078 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9080 if (!Printer) {
9081 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9082 return WERR_BADFID;
9085 if (!get_printer_snum(p, handle, &snum))
9086 return WERR_BADFID;
9088 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9089 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9090 return WERR_ACCESS_DENIED;
9093 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9094 if (!W_ERROR_IS_OK(status))
9095 return status;
9097 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9098 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9100 status = delete_printer_dataex( printer, keyname, valuename );
9102 if ( W_ERROR_IS_OK(status) )
9103 mod_a_printer( printer, 2 );
9105 free_a_printer(&printer, 2);
9107 return status;
9110 /********************************************************************
9111 * spoolss_enumprinterkey
9112 ********************************************************************/
9115 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9117 fstring key;
9118 fstring *keynames = NULL;
9119 uint16 *enumkeys = NULL;
9120 int num_keys;
9121 int printerkey_len;
9122 POLICY_HND *handle = &q_u->handle;
9123 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9124 NT_PRINTER_DATA *data;
9125 NT_PRINTER_INFO_LEVEL *printer = NULL;
9126 int snum = 0;
9127 WERROR status = WERR_BADFILE;
9130 DEBUG(4,("_spoolss_enumprinterkey\n"));
9132 if (!Printer) {
9133 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9134 return WERR_BADFID;
9137 if ( !get_printer_snum(p,handle, &snum) )
9138 return WERR_BADFID;
9140 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9141 if (!W_ERROR_IS_OK(status))
9142 return status;
9144 /* get the list of subkey names */
9146 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9147 data = printer->info_2->data;
9149 num_keys = get_printer_subkeys( data, key, &keynames );
9151 if ( num_keys == -1 ) {
9152 status = WERR_BADFILE;
9153 goto done;
9156 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9158 r_u->needed = printerkey_len*2;
9160 if ( q_u->size < r_u->needed ) {
9161 status = WERR_MORE_DATA;
9162 goto done;
9165 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9166 status = WERR_NOMEM;
9167 goto done;
9170 status = WERR_OK;
9172 if ( q_u->size < r_u->needed )
9173 status = WERR_MORE_DATA;
9175 done:
9176 free_a_printer( &printer, 2 );
9177 SAFE_FREE( keynames );
9179 return status;
9182 /********************************************************************
9183 * spoolss_deleteprinterkey
9184 ********************************************************************/
9186 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9188 POLICY_HND *handle = &q_u->handle;
9189 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9190 fstring key;
9191 NT_PRINTER_INFO_LEVEL *printer = NULL;
9192 int snum=0;
9193 WERROR status;
9195 DEBUG(5,("spoolss_deleteprinterkey\n"));
9197 if (!Printer) {
9198 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9199 return WERR_BADFID;
9202 /* if keyname == NULL, return error */
9204 if ( !q_u->keyname.buffer )
9205 return WERR_INVALID_PARAM;
9207 if (!get_printer_snum(p, handle, &snum))
9208 return WERR_BADFID;
9210 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9211 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9212 return WERR_ACCESS_DENIED;
9215 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9216 if (!W_ERROR_IS_OK(status))
9217 return status;
9219 /* delete the key and all subneys */
9221 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9223 status = delete_all_printer_data( printer->info_2, key );
9225 if ( W_ERROR_IS_OK(status) )
9226 status = mod_a_printer(printer, 2);
9228 free_a_printer( &printer, 2 );
9230 return status;
9234 /********************************************************************
9235 * spoolss_enumprinterdataex
9236 ********************************************************************/
9238 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9240 POLICY_HND *handle = &q_u->handle;
9241 uint32 in_size = q_u->size;
9242 uint32 num_entries,
9243 needed;
9244 NT_PRINTER_INFO_LEVEL *printer = NULL;
9245 PRINTER_ENUM_VALUES *enum_values = NULL;
9246 NT_PRINTER_DATA *p_data;
9247 fstring key;
9248 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9249 int snum;
9250 WERROR result;
9251 int key_index;
9252 int i;
9253 REGISTRY_VALUE *val;
9254 char *value_name;
9255 uint32 data_len;
9258 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9260 if (!Printer) {
9261 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9262 return WERR_BADFID;
9266 * first check for a keyname of NULL or "". Win2k seems to send
9267 * this a lot and we should send back WERR_INVALID_PARAM
9268 * no need to spend time looking up the printer in this case.
9269 * --jerry
9272 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9273 if ( !strlen(key) ) {
9274 result = WERR_INVALID_PARAM;
9275 goto done;
9278 /* get the printer off of disk */
9280 if (!get_printer_snum(p,handle, &snum))
9281 return WERR_BADFID;
9283 ZERO_STRUCT(printer);
9284 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9285 if (!W_ERROR_IS_OK(result))
9286 return result;
9288 /* now look for a match on the key name */
9290 p_data = printer->info_2->data;
9292 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9293 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9295 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9296 result = WERR_INVALID_PARAM;
9297 goto done;
9300 result = WERR_OK;
9301 needed = 0;
9303 /* allocate the memory for the array of pointers -- if necessary */
9305 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9306 if ( num_entries )
9308 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9310 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9311 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9312 result = WERR_NOMEM;
9313 goto done;
9316 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9320 * loop through all params and build the array to pass
9321 * back to the client
9324 for ( i=0; i<num_entries; i++ )
9326 /* lookup the registry value */
9328 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9329 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9331 /* copy the data */
9333 value_name = regval_name( val );
9334 init_unistr( &enum_values[i].valuename, value_name );
9335 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9336 enum_values[i].type = regval_type( val );
9338 data_len = regval_size( val );
9339 if ( data_len ) {
9340 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9342 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9343 data_len ));
9344 result = WERR_NOMEM;
9345 goto done;
9348 enum_values[i].data_len = data_len;
9350 /* keep track of the size of the array in bytes */
9352 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9355 /* housekeeping information in the reply */
9357 r_u->needed = needed;
9358 r_u->returned = num_entries;
9360 if (needed > in_size) {
9361 result = WERR_MORE_DATA;
9362 goto done;
9365 /* copy data into the reply */
9367 r_u->ctr.size = r_u->needed;
9368 r_u->ctr.size_of_array = r_u->returned;
9369 r_u->ctr.values = enum_values;
9373 done:
9374 if ( printer )
9375 free_a_printer(&printer, 2);
9377 return result;
9380 /****************************************************************************
9381 ****************************************************************************/
9383 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9385 init_unistr(&info->name, name);
9388 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9389 UNISTR2 *environment,
9390 RPC_BUFFER *buffer,
9391 uint32 offered,
9392 uint32 *needed)
9394 pstring path;
9395 pstring long_archi;
9396 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9397 WERROR result = WERR_OK;
9399 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9401 if (!get_short_archi(long_archi))
9402 return WERR_INVALID_ENVIRONMENT;
9404 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9405 return WERR_NOMEM;
9407 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9409 fill_printprocessordirectory_1(info, path);
9411 *needed += spoolss_size_printprocessordirectory_info_1(info);
9413 if (*needed > offered) {
9414 result = WERR_INSUFFICIENT_BUFFER;
9415 goto out;
9418 if (!rpcbuf_alloc_size(buffer, *needed)) {
9419 result = WERR_INSUFFICIENT_BUFFER;
9420 goto out;
9423 smb_io_printprocessordirectory_1("", buffer, info, 0);
9425 out:
9426 SAFE_FREE(info);
9428 return result;
9431 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9433 uint32 level = q_u->level;
9434 RPC_BUFFER *buffer = NULL;
9435 uint32 offered = q_u->offered;
9436 uint32 *needed = &r_u->needed;
9437 WERROR result;
9439 /* that's an [in out] buffer */
9441 if (!q_u->buffer) {
9442 return WERR_INVALID_PARAM;
9445 rpcbuf_move(q_u->buffer, &r_u->buffer);
9446 buffer = r_u->buffer;
9448 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9450 *needed=0;
9452 switch(level) {
9453 case 1:
9454 result = getprintprocessordirectory_level_1
9455 (&q_u->name, &q_u->environment, buffer, offered, needed);
9456 break;
9457 default:
9458 result = WERR_UNKNOWN_LEVEL;
9461 return result;
9464 /*******************************************************************
9465 Streams the monitor UI DLL name in UNICODE
9466 *******************************************************************/
9468 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9469 RPC_BUFFER *out, uint32 *needed )
9471 const char *dllname = "tcpmonui.dll";
9473 *needed = (strlen(dllname)+1) * 2;
9475 if ( rpcbuf_get_size(out) < *needed ) {
9476 return WERR_INSUFFICIENT_BUFFER;
9479 if ( !make_monitorui_buf( out, dllname ) ) {
9480 return WERR_NOMEM;
9483 return WERR_OK;
9486 /*******************************************************************
9487 Create a new TCP/IP port
9488 *******************************************************************/
9490 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9491 RPC_BUFFER *out, uint32 *needed )
9493 NT_PORT_DATA_1 port1;
9494 pstring device_uri;
9496 ZERO_STRUCT( port1 );
9498 /* convert to our internal port data structure */
9500 if ( !convert_port_data_1( &port1, in ) ) {
9501 return WERR_NOMEM;
9504 /* create the device URI and call the add_port_hook() */
9506 switch ( port1.protocol ) {
9507 case PORT_PROTOCOL_DIRECT:
9508 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9509 break;
9511 case PORT_PROTOCOL_LPR:
9512 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9513 break;
9515 default:
9516 return WERR_UNKNOWN_PORT;
9519 return add_port_hook( token, port1.name, device_uri );
9522 /*******************************************************************
9523 *******************************************************************/
9525 struct xcv_api_table xcvtcp_cmds[] = {
9526 { "MonitorUI", xcvtcp_monitorui },
9527 { "AddPort", xcvtcp_addport},
9528 { NULL, NULL }
9531 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9532 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9533 uint32 *needed )
9535 int i;
9537 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9539 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9540 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9541 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9544 return WERR_BADFUNC;
9547 /*******************************************************************
9548 *******************************************************************/
9549 #if 0 /* don't support management using the "Local Port" monitor */
9551 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9552 RPC_BUFFER *out, uint32 *needed )
9554 const char *dllname = "localui.dll";
9556 *needed = (strlen(dllname)+1) * 2;
9558 if ( rpcbuf_get_size(out) < *needed ) {
9559 return WERR_INSUFFICIENT_BUFFER;
9562 if ( !make_monitorui_buf( out, dllname )) {
9563 return WERR_NOMEM;
9566 return WERR_OK;
9569 /*******************************************************************
9570 *******************************************************************/
9572 struct xcv_api_table xcvlocal_cmds[] = {
9573 { "MonitorUI", xcvlocal_monitorui },
9574 { NULL, NULL }
9576 #else
9577 struct xcv_api_table xcvlocal_cmds[] = {
9578 { NULL, NULL }
9580 #endif
9584 /*******************************************************************
9585 *******************************************************************/
9587 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9588 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9589 uint32 *needed )
9591 int i;
9593 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9595 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9596 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9597 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9599 return WERR_BADFUNC;
9602 /*******************************************************************
9603 *******************************************************************/
9605 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9607 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9608 fstring command;
9610 if (!Printer) {
9611 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9612 return WERR_BADFID;
9615 /* Has to be a handle to the TCP/IP port monitor */
9617 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9618 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9619 return WERR_BADFID;
9622 /* requires administrative access to the server */
9624 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9625 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9626 return WERR_ACCESS_DENIED;
9629 /* Get the command name. There's numerous commands supported by the
9630 TCPMON interface. */
9632 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9633 q_u->dataname.uni_str_len*2, 0);
9635 /* Allocate the outgoing buffer */
9637 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9639 switch ( Printer->printer_type ) {
9640 case SPLHND_PORTMON_TCP:
9641 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9642 &q_u->indata, &r_u->outdata, &r_u->needed );
9643 case SPLHND_PORTMON_LOCAL:
9644 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9645 &q_u->indata, &r_u->outdata, &r_u->needed );
9648 return WERR_INVALID_PRINT_MONITOR;