r6303: Setting up for 3.0.15pre1
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob0f33fd7dec87c113b6167ae8069982652dca5979
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 cli_state notify_cli; /* print notify back-channel */
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())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
92 switch (v) {
93 case LPQ_QUEUED:
94 return 0;
95 case LPQ_PAUSED:
96 return JOB_STATUS_PAUSED;
97 case LPQ_SPOOLING:
98 return JOB_STATUS_SPOOLING;
99 case LPQ_PRINTING:
100 return JOB_STATUS_PRINTING;
101 case LPQ_ERROR:
102 return JOB_STATUS_ERROR;
103 case LPQ_DELETING:
104 return JOB_STATUS_DELETING;
105 case LPQ_OFFLINE:
106 return JOB_STATUS_OFFLINE;
107 case LPQ_PAPEROUT:
108 return JOB_STATUS_PAPEROUT;
109 case LPQ_PRINTED:
110 return JOB_STATUS_PRINTED;
111 case LPQ_DELETED:
112 return JOB_STATUS_DELETED;
113 case LPQ_BLOCKED:
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
118 return 0;
121 static int nt_printq_status(int v)
123 switch (v) {
124 case LPQ_PAUSED:
125 return PRINTER_STATUS_PAUSED;
126 case LPQ_QUEUED:
127 case LPQ_SPOOLING:
128 case LPQ_PRINTING:
129 return 0;
131 return 0;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
140 if (*pp == NULL)
141 return;
143 SAFE_FREE((*pp)->ctr.type);
144 SAFE_FREE(*pp);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
153 WERROR result;
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166 return;
169 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
171 if (!W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
177 cli_nt_session_close(&notify_cli);
178 cli_ulogoff(&notify_cli);
179 cli_shutdown(&notify_cli);
180 message_deregister(MSG_PRINTER_NOTIFY2);
182 /* Tell the connections db we're no longer interested in
183 * printer notify messages. */
185 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
188 smb_connections--;
191 /****************************************************************************
192 Functions to free a printer entry datastruct.
193 ****************************************************************************/
195 static void free_printer_entry(void *ptr)
197 Printer_entry *Printer = (Printer_entry *)ptr;
199 if (Printer->notify.client_connected==True) {
200 int snum = -1;
202 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
203 snum = -1;
204 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
205 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
206 snum = print_queue_snum(Printer->sharename);
207 if (snum != -1)
208 srv_spoolss_replycloseprinter(snum,
209 &Printer->notify.client_hnd);
213 Printer->notify.flags=0;
214 Printer->notify.options=0;
215 Printer->notify.localmachine[0]='\0';
216 Printer->notify.printerlocal=0;
217 free_spool_notify_option(&Printer->notify.option);
218 Printer->notify.option=NULL;
219 Printer->notify.client_connected=False;
221 free_nt_devicemode( &Printer->nt_devmode );
222 free_a_printer( &Printer->printer_info, 2 );
224 talloc_destroy( Printer->ctx );
226 /* Remove from the internal list. */
227 DLIST_REMOVE(printers_list, Printer);
229 SAFE_FREE(Printer);
232 /****************************************************************************
233 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
234 ****************************************************************************/
236 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
238 SPOOL_NOTIFY_OPTION *new_sp = NULL;
240 if (!sp)
241 return NULL;
243 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
244 if (!new_sp)
245 return NULL;
247 *new_sp = *sp;
249 if (sp->ctr.count) {
250 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
252 if (!new_sp->ctr.type) {
253 SAFE_FREE(new_sp);
254 return NULL;
258 return new_sp;
261 /****************************************************************************
262 find printer index by handle
263 ****************************************************************************/
265 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
267 Printer_entry *find_printer = NULL;
269 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
270 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
271 return NULL;
274 return find_printer;
277 /****************************************************************************
278 look for a printer object cached on an open printer handle
279 ****************************************************************************/
281 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
282 const char *servername, const char *printername )
284 Printer_entry *p;
286 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
287 servername, printername));
289 for ( p=printers_list; p; p=p->next )
291 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
292 && p->printer_info
293 && strequal( p->sharename, printername )
294 && strequal( p->servername, servername ) )
296 DEBUG(10,("Found printer\n"));
297 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
298 if ( *info2 )
299 return WERR_OK;
303 return WERR_INVALID_PRINTER_NAME;
306 /****************************************************************************
307 destroy any cached printer_info_2 structures on open handles
308 ****************************************************************************/
310 void invalidate_printer_hnd_cache( char *printername )
312 Printer_entry *p;
314 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
316 for ( p=printers_list; p; p=p->next )
318 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
319 && p->printer_info
320 && StrCaseCmp(p->sharename, printername)==0)
322 DEBUG(10,("invalidating printer_info cache for handl:\n"));
323 free_a_printer( &p->printer_info, 2 );
324 p->printer_info = NULL;
328 return;
330 /****************************************************************************
331 Close printer index by handle.
332 ****************************************************************************/
334 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
336 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
338 if (!Printer) {
339 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
340 return False;
343 close_policy_hnd(p, hnd);
345 return True;
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
356 if (!Printer) {
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
358 return WERR_BADFID;
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
365 * JRA.
368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED;
373 #if 0
374 /* Check calling user has permission to delete printer. Note that
375 since we set the snum parameter to -1 only administrators can
376 delete the printer. This stops people with the Full Control
377 permission from deleting the printer. */
379 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
380 DEBUG(3, ("printer delete denied by security descriptor\n"));
381 return WERR_ACCESS_DENIED;
383 #endif
385 /* this does not need a become root since the access check has been
386 done on the handle already */
388 if (del_a_printer( Printer->sharename ) != 0) {
389 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
390 return WERR_BADFID;
393 /* the delete printer script shoudl be run as root if the user has perms */
395 if (*lp_deleteprinter_cmd()) {
397 char *cmd = lp_deleteprinter_cmd();
398 pstring command;
399 int ret;
400 SE_PRIV se_printop = SE_PRINT_OPERATOR;
401 BOOL is_print_op;
403 pstr_sprintf(command, "%s \"%s\"", cmd, Printer->sharename);
405 is_print_op = user_has_privileges( p->pipe_user.nt_user_token, &se_printop );
407 DEBUG(10,("Running [%s]\n", command));
409 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
411 if ( is_print_op )
412 become_root();
414 if ( (ret = smbrun(command, NULL)) == 0 ) {
415 /* Tell everyone we updated smb.conf. */
416 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
419 if ( is_print_op )
420 unbecome_root();
422 /********** END SePrintOperatorPrivlege BLOCK **********/
424 DEBUGADD(10,("returned [%d]\n", ret));
426 if (ret != 0)
427 return WERR_BADFID; /* What to return here? */
429 /* go ahead and re-read the services immediately */
430 reload_services( False );
432 if ( lp_servicenumber( Printer->sharename ) < 0 )
433 return WERR_ACCESS_DENIED;
436 return WERR_OK;
439 /****************************************************************************
440 Return the snum of a printer corresponding to an handle.
441 ****************************************************************************/
443 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
445 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
447 if (!Printer) {
448 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
449 return False;
452 switch (Printer->printer_type) {
453 case PRINTER_HANDLE_IS_PRINTER:
454 DEBUG(4,("short name:%s\n", Printer->sharename));
455 *number = print_queue_snum(Printer->sharename);
456 return (*number != -1);
457 case PRINTER_HANDLE_IS_PRINTSERVER:
458 return False;
459 default:
460 return False;
464 /****************************************************************************
465 Set printer handle type.
466 Check if it's \\server or \\server\printer
467 ****************************************************************************/
469 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
471 DEBUG(3,("Setting printer type=%s\n", handlename));
473 if ( strlen(handlename) < 3 ) {
474 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
475 return False;
478 /* it's a print server */
479 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
480 DEBUGADD(4,("Printer is a print server\n"));
481 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
483 /* it's a printer */
484 else {
485 DEBUGADD(4,("Printer is a printer\n"));
486 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
489 return True;
492 /****************************************************************************
493 Set printer handle name.
494 ****************************************************************************/
496 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
498 int snum;
499 int n_services=lp_numservices();
500 char *aprinter, *printername;
501 const char *servername;
502 fstring sname;
503 BOOL found=False;
504 NT_PRINTER_INFO_LEVEL *printer;
505 WERROR result;
507 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
509 aprinter = handlename;
510 if ( *handlename == '\\' ) {
511 servername = handlename + 2;
512 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
513 *aprinter = '\0';
514 aprinter++;
517 else {
518 servername = "";
521 /* save the servername to fill in replies on this handle */
523 if ( !is_myname_or_ipaddr( servername ) )
524 return False;
526 fstrcpy( Printer->servername, servername );
528 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
529 return True;
531 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
532 return False;
534 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
536 /* Search all sharenames first as this is easier than pulling
537 the printer_info_2 off of disk */
539 snum = find_service(aprinter);
541 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
542 found = True;
543 fstrcpy( sname, aprinter );
546 /* do another loop to look for printernames */
548 for (snum=0; !found && snum<n_services; snum++) {
550 /* no point in checking if this is not a printer or
551 we aren't allowing printername != sharename */
553 if ( !(lp_snum_ok(snum)
554 && lp_print_ok(snum)
555 && !lp_force_printername(snum)) )
557 continue;
560 fstrcpy(sname, lp_servicename(snum));
562 printer = NULL;
563 result = get_a_printer( NULL, &printer, 2, sname );
564 if ( !W_ERROR_IS_OK(result) ) {
565 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
566 sname, dos_errstr(result)));
567 continue;
570 /* printername is always returned as \\server\printername */
571 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
572 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
573 printer->info_2->printername));
574 free_a_printer( &printer, 2);
575 continue;
578 printername++;
580 if ( strequal(printername, aprinter) ) {
581 found = True;
584 DEBUGADD(10, ("printername: %s\n", printername));
586 free_a_printer( &printer, 2);
589 if ( !found ) {
590 DEBUGADD(4,("Printer not found\n"));
591 return False;
594 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
596 fstrcpy(Printer->sharename, sname);
598 return True;
601 /****************************************************************************
602 Find first available printer slot. creates a printer handle for you.
603 ****************************************************************************/
605 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
607 Printer_entry *new_printer;
609 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
611 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
612 return False;
614 ZERO_STRUCTP(new_printer);
616 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
617 SAFE_FREE(new_printer);
618 return False;
621 /* Add to the internal list. */
622 DLIST_ADD(printers_list, new_printer);
624 new_printer->notify.option=NULL;
626 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
627 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
628 close_printer_handle(p, hnd);
629 return False;
632 if (!set_printer_hnd_printertype(new_printer, name)) {
633 close_printer_handle(p, hnd);
634 return False;
637 if (!set_printer_hnd_name(new_printer, name)) {
638 close_printer_handle(p, hnd);
639 return False;
642 new_printer->access_granted = access_granted;
644 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
646 return True;
649 /***************************************************************************
650 check to see if the client motify handle is monitoring the notification
651 given by (notify_type, notify_field).
652 **************************************************************************/
654 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
655 uint16 notify_field)
657 return True;
660 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
661 uint16 notify_field)
663 SPOOL_NOTIFY_OPTION *option = p->notify.option;
664 uint32 i, j;
667 * Flags should always be zero when the change notify
668 * is registered by the client's spooler. A user Win32 app
669 * might use the flags though instead of the NOTIFY_OPTION_INFO
670 * --jerry
673 if (!option) {
674 return False;
677 if (p->notify.flags)
678 return is_monitoring_event_flags(
679 p->notify.flags, notify_type, notify_field);
681 for (i = 0; i < option->count; i++) {
683 /* Check match for notify_type */
685 if (option->ctr.type[i].type != notify_type)
686 continue;
688 /* Check match for field */
690 for (j = 0; j < option->ctr.type[i].count; j++) {
691 if (option->ctr.type[i].fields[j] == notify_field) {
692 return True;
697 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
698 p->servername, p->sharename, notify_type, notify_field));
700 return False;
703 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
705 static void notify_one_value(struct spoolss_notify_msg *msg,
706 SPOOL_NOTIFY_INFO_DATA *data,
707 TALLOC_CTX *mem_ctx)
709 data->notify_data.value[0] = msg->notify.value[0];
710 data->notify_data.value[1] = 0;
713 static void notify_string(struct spoolss_notify_msg *msg,
714 SPOOL_NOTIFY_INFO_DATA *data,
715 TALLOC_CTX *mem_ctx)
717 UNISTR2 unistr;
719 /* The length of the message includes the trailing \0 */
721 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
723 data->notify_data.data.length = msg->len * 2;
724 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
726 if (!data->notify_data.data.string) {
727 data->notify_data.data.length = 0;
728 return;
731 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
734 static void notify_system_time(struct spoolss_notify_msg *msg,
735 SPOOL_NOTIFY_INFO_DATA *data,
736 TALLOC_CTX *mem_ctx)
738 SYSTEMTIME systime;
739 prs_struct ps;
741 if (msg->len != sizeof(time_t)) {
742 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
743 msg->len));
744 return;
747 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
748 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
749 return;
752 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
753 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
754 return;
757 if (!spoolss_io_system_time("", &ps, 0, &systime))
758 return;
760 data->notify_data.data.length = prs_offset(&ps);
761 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
763 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
765 prs_mem_free(&ps);
768 struct notify2_message_table {
769 const char *name;
770 void (*fn)(struct spoolss_notify_msg *msg,
771 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
774 static struct notify2_message_table printer_notify_table[] = {
775 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
776 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
777 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
778 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
779 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
780 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
781 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
782 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
783 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
784 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
785 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
786 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
787 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
788 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
789 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
790 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
791 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
792 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
793 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
796 static struct notify2_message_table job_notify_table[] = {
797 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
798 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
799 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
800 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
801 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
802 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
803 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
804 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
805 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
806 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
807 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
808 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
809 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
810 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
811 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
812 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
813 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
814 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
815 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
816 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
817 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
818 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
819 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
820 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
824 /***********************************************************************
825 Allocate talloc context for container object
826 **********************************************************************/
828 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
830 if ( !ctr )
831 return;
833 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
835 return;
838 /***********************************************************************
839 release all allocated memory and zero out structure
840 **********************************************************************/
842 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
844 if ( !ctr )
845 return;
847 if ( ctr->ctx )
848 talloc_destroy(ctr->ctx);
850 ZERO_STRUCTP(ctr);
852 return;
855 /***********************************************************************
856 **********************************************************************/
858 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 if ( !ctr )
861 return NULL;
863 return ctr->ctx;
866 /***********************************************************************
867 **********************************************************************/
869 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
871 if ( !ctr || !ctr->msg_groups )
872 return NULL;
874 if ( idx >= ctr->num_groups )
875 return NULL;
877 return &ctr->msg_groups[idx];
881 /***********************************************************************
882 How many groups of change messages do we have ?
883 **********************************************************************/
885 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
887 if ( !ctr )
888 return 0;
890 return ctr->num_groups;
893 /***********************************************************************
894 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
895 **********************************************************************/
897 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
899 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
900 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
901 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
902 int i, new_slot;
904 if ( !ctr || !msg )
905 return 0;
907 /* loop over all groups looking for a matching printer name */
909 for ( i=0; i<ctr->num_groups; i++ ) {
910 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
911 break;
914 /* add a new group? */
916 if ( i == ctr->num_groups ) {
917 ctr->num_groups++;
919 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
920 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
921 return 0;
923 ctr->msg_groups = groups;
925 /* clear the new entry and set the printer name */
927 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
928 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
931 /* add the change messages; 'i' is the correct index now regardless */
933 msg_grp = &ctr->msg_groups[i];
935 msg_grp->num_msgs++;
937 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
938 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
939 return 0;
941 msg_grp->msgs = msg_list;
943 new_slot = msg_grp->num_msgs-1;
944 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
946 /* need to allocate own copy of data */
948 if ( msg->len != 0 )
949 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
951 return ctr->num_groups;
954 /***********************************************************************
955 Send a change notication message on all handles which have a call
956 back registered
957 **********************************************************************/
959 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
961 Printer_entry *p;
962 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
963 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
964 SPOOLSS_NOTIFY_MSG *messages;
965 int sending_msg_count;
967 if ( !msg_group ) {
968 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
969 return;
972 messages = msg_group->msgs;
974 if ( !messages ) {
975 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
976 return;
979 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
981 /* loop over all printers */
983 for (p = printers_list; p; p = p->next) {
984 SPOOL_NOTIFY_INFO_DATA *data;
985 uint32 data_len = 0;
986 uint32 id;
987 int i;
989 /* Is there notification on this handle? */
991 if ( !p->notify.client_connected )
992 continue;
994 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
996 /* For this printer? Print servers always receive
997 notifications. */
999 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1000 ( !strequal(msg_group->printername, p->sharename) ) )
1001 continue;
1003 DEBUG(10,("Our printer\n"));
1005 /* allocate the max entries possible */
1007 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1008 ZERO_STRUCTP(data);
1010 /* build the array of change notifications */
1012 sending_msg_count = 0;
1014 for ( i=0; i<msg_group->num_msgs; i++ ) {
1015 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1017 /* Are we monitoring this event? */
1019 if (!is_monitoring_event(p, msg->type, msg->field))
1020 continue;
1022 sending_msg_count++;
1025 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1026 msg->type, msg->field, p->sharename));
1029 * if the is a printer notification handle and not a job notification
1030 * type, then set the id to 0. Other wise just use what was specified
1031 * in the message.
1033 * When registering change notification on a print server handle
1034 * we always need to send back the id (snum) matching the printer
1035 * for which the change took place. For change notify registered
1036 * on a printer handle, this does not matter and the id should be 0.
1038 * --jerry
1041 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1042 id = 0;
1043 else
1044 id = msg->id;
1047 /* Convert unix jobid to smb jobid */
1049 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1050 id = sysjob_to_jobid(msg->id);
1052 if (id == -1) {
1053 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1054 goto done;
1058 construct_info_data( &data[data_len], msg->type, msg->field, id );
1060 switch(msg->type) {
1061 case PRINTER_NOTIFY_TYPE:
1062 if ( printer_notify_table[msg->field].fn )
1063 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1064 break;
1066 case JOB_NOTIFY_TYPE:
1067 if ( job_notify_table[msg->field].fn )
1068 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1069 break;
1071 default:
1072 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1073 goto done;
1076 data_len++;
1079 if ( sending_msg_count ) {
1080 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1081 data_len, data, p->notify.change, 0 );
1085 done:
1086 DEBUG(8,("send_notify2_changes: Exit...\n"));
1087 return;
1090 /***********************************************************************
1091 **********************************************************************/
1093 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1096 uint32 tv_sec, tv_usec;
1097 size_t offset = 0;
1099 /* Unpack message */
1101 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1102 msg->printer);
1104 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1105 &tv_sec, &tv_usec,
1106 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1108 if (msg->len == 0)
1109 tdb_unpack((char *)buf + offset, len - offset, "dd",
1110 &msg->notify.value[0], &msg->notify.value[1]);
1111 else
1112 tdb_unpack((char *)buf + offset, len - offset, "B",
1113 &msg->len, &msg->notify.data);
1115 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1116 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1118 tv->tv_sec = tv_sec;
1119 tv->tv_usec = tv_usec;
1121 if (msg->len == 0)
1122 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1123 msg->notify.value[1]));
1124 else
1125 dump_data(3, msg->notify.data, msg->len);
1127 return True;
1130 /********************************************************************
1131 Receive a notify2 message list
1132 ********************************************************************/
1134 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1136 size_t msg_count, i;
1137 char *buf = (char *)msg;
1138 char *msg_ptr;
1139 size_t msg_len;
1140 SPOOLSS_NOTIFY_MSG notify;
1141 SPOOLSS_NOTIFY_MSG_CTR messages;
1142 int num_groups;
1144 if (len < 4) {
1145 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1146 return;
1149 msg_count = IVAL(buf, 0);
1150 msg_ptr = buf + 4;
1152 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1154 if (msg_count == 0) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1156 return;
1159 /* initialize the container */
1161 ZERO_STRUCT( messages );
1162 notify_msg_ctr_init( &messages );
1165 * build message groups for each printer identified
1166 * in a change_notify msg. Remember that a PCN message
1167 * includes the handle returned for the srv_spoolss_replyopenprinter()
1168 * call. Therefore messages are grouped according to printer handle.
1171 for ( i=0; i<msg_count; i++ ) {
1172 struct timeval msg_tv;
1174 if (msg_ptr + 4 - buf > len) {
1175 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1176 return;
1179 msg_len = IVAL(msg_ptr,0);
1180 msg_ptr += 4;
1182 if (msg_ptr + msg_len - buf > len) {
1183 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1184 return;
1187 /* unpack messages */
1189 ZERO_STRUCT( notify );
1190 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1191 msg_ptr += msg_len;
1193 /* add to correct list in container */
1195 notify_msg_ctr_addmsg( &messages, &notify );
1197 /* free memory that might have been allocated by notify2_unpack_msg() */
1199 if ( notify.len != 0 )
1200 SAFE_FREE( notify.notify.data );
1203 /* process each group of messages */
1205 num_groups = notify_msg_ctr_numgroups( &messages );
1206 for ( i=0; i<num_groups; i++ )
1207 send_notify2_changes( &messages, i );
1210 /* cleanup */
1212 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1214 notify_msg_ctr_destroy( &messages );
1216 return;
1219 /********************************************************************
1220 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1221 one smbd, all of processes must clear their printer cache immediately.
1222 ********************************************************************/
1224 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1226 fstring printername;
1228 fstrcpy( printername, buf );
1230 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1232 invalidate_printer_hnd_cache( printername );
1235 /********************************************************************
1236 Send a message to ourself about new driver being installed
1237 so we can upgrade the information for each printer bound to this
1238 driver
1239 ********************************************************************/
1241 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1243 int len = strlen(drivername);
1245 if (!len)
1246 return False;
1248 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1249 drivername));
1251 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1253 return True;
1256 /**********************************************************************
1257 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1258 over all printers, upgrading ones as necessary
1259 **********************************************************************/
1261 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1263 fstring drivername;
1264 int snum;
1265 int n_services = lp_numservices();
1267 len = MIN(len,sizeof(drivername)-1);
1268 strncpy(drivername, buf, len);
1270 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1272 /* Iterate the printer list */
1274 for (snum=0; snum<n_services; snum++)
1276 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1278 WERROR result;
1279 NT_PRINTER_INFO_LEVEL *printer = NULL;
1281 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1282 if (!W_ERROR_IS_OK(result))
1283 continue;
1285 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1287 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1289 /* all we care about currently is the change_id */
1291 result = mod_a_printer(printer, 2);
1292 if (!W_ERROR_IS_OK(result)) {
1293 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1294 dos_errstr(result)));
1298 free_a_printer(&printer, 2);
1302 /* all done */
1305 /********************************************************************
1306 Update the cache for all printq's with a registered client
1307 connection
1308 ********************************************************************/
1310 void update_monitored_printq_cache( void )
1312 Printer_entry *printer = printers_list;
1313 int snum;
1315 /* loop through all printers and update the cache where
1316 client_connected == True */
1317 while ( printer )
1319 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1320 && printer->notify.client_connected )
1322 snum = print_queue_snum(printer->sharename);
1323 print_queue_status( snum, NULL, NULL );
1326 printer = printer->next;
1329 return;
1331 /********************************************************************
1332 Send a message to ourself about new driver being installed
1333 so we can upgrade the information for each printer bound to this
1334 driver
1335 ********************************************************************/
1337 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1339 int len = strlen(drivername);
1341 if (!len)
1342 return False;
1344 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1345 drivername));
1347 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1349 return True;
1352 /**********************************************************************
1353 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1354 over all printers, resetting printer data as neessary
1355 **********************************************************************/
1357 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1359 fstring drivername;
1360 int snum;
1361 int n_services = lp_numservices();
1363 len = MIN( len, sizeof(drivername)-1 );
1364 strncpy( drivername, buf, len );
1366 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1368 /* Iterate the printer list */
1370 for ( snum=0; snum<n_services; snum++ )
1372 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1374 WERROR result;
1375 NT_PRINTER_INFO_LEVEL *printer = NULL;
1377 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1378 if ( !W_ERROR_IS_OK(result) )
1379 continue;
1382 * if the printer is bound to the driver,
1383 * then reset to the new driver initdata
1386 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1388 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1390 if ( !set_driver_init(printer, 2) ) {
1391 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1392 printer->info_2->printername, printer->info_2->drivername));
1395 result = mod_a_printer( printer, 2 );
1396 if ( !W_ERROR_IS_OK(result) ) {
1397 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1398 get_dos_error_msg(result)));
1402 free_a_printer( &printer, 2 );
1406 /* all done */
1408 return;
1411 /********************************************************************
1412 Copy routines used by convert_to_openprinterex()
1413 *******************************************************************/
1415 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1417 DEVICEMODE *d;
1418 int len;
1420 if (!devmode)
1421 return NULL;
1423 DEBUG (8,("dup_devmode\n"));
1425 /* bulk copy first */
1427 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1428 if (!d)
1429 return NULL;
1431 /* dup the pointer members separately */
1433 len = unistrlen(devmode->devicename.buffer);
1434 if (len != -1) {
1435 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1436 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1437 return NULL;
1441 len = unistrlen(devmode->formname.buffer);
1442 if (len != -1) {
1443 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1444 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1445 return NULL;
1448 d->private = TALLOC_MEMDUP(ctx, devmode->private, devmode->driverextra);
1450 return d;
1453 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1455 if (!new_ctr || !ctr)
1456 return;
1458 DEBUG(8,("copy_devmode_ctr\n"));
1460 new_ctr->size = ctr->size;
1461 new_ctr->devmode_ptr = ctr->devmode_ptr;
1463 if(ctr->devmode_ptr)
1464 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1467 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1469 if (!new_def || !def)
1470 return;
1472 DEBUG(8,("copy_printer_defaults\n"));
1474 new_def->datatype_ptr = def->datatype_ptr;
1476 if (def->datatype_ptr)
1477 copy_unistr2(&new_def->datatype, &def->datatype);
1479 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1481 new_def->access_required = def->access_required;
1484 /********************************************************************
1485 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1486 * SPOOL_Q_OPEN_PRINTER_EX structure
1487 ********************************************************************/
1489 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1491 if (!q_u_ex || !q_u)
1492 return;
1494 DEBUG(8,("convert_to_openprinterex\n"));
1496 if ( q_u->printername ) {
1497 q_u_ex->printername = TALLOC_P( ctx, UNISTR2 );
1498 copy_unistr2(q_u_ex->printername, q_u->printername);
1501 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1504 /********************************************************************
1505 * spoolss_open_printer
1507 * called from the spoolss dispatcher
1508 ********************************************************************/
1510 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1512 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1513 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1515 if (!q_u || !r_u)
1516 return WERR_NOMEM;
1518 ZERO_STRUCT(q_u_ex);
1519 ZERO_STRUCT(r_u_ex);
1521 /* convert the OpenPrinter() call to OpenPrinterEx() */
1523 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1525 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1527 /* convert back to OpenPrinter() */
1529 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1531 return r_u->status;
1534 /********************************************************************
1535 * spoolss_open_printer
1537 * If the openprinterex rpc call contains a devmode,
1538 * it's a per-user one. This per-user devmode is derivated
1539 * from the global devmode. Openprinterex() contains a per-user
1540 * devmode for when you do EMF printing and spooling.
1541 * In the EMF case, the NT workstation is only doing half the job
1542 * of rendering the page. The other half is done by running the printer
1543 * driver on the server.
1544 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1545 * The EMF file only contains what is to be printed on the page.
1546 * So in order for the server to know how to print, the NT client sends
1547 * a devicemode attached to the openprinterex call.
1548 * But this devicemode is short lived, it's only valid for the current print job.
1550 * If Samba would have supported EMF spooling, this devicemode would
1551 * have been attached to the handle, to sent it to the driver to correctly
1552 * rasterize the EMF file.
1554 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1555 * we just act as a pass-thru between windows and the printer.
1557 * In order to know that Samba supports only RAW spooling, NT has to call
1558 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1559 * and until NT sends a RAW job, we refuse it.
1561 * But to call getprinter() or startdoc(), you first need a valid handle,
1562 * and to get an handle you have to call openprintex(). Hence why you have
1563 * a devicemode in the openprinterex() call.
1566 * Differences between NT4 and NT 2000.
1567 * NT4:
1568 * ---
1569 * On NT4, you only have a global devicemode. This global devicemode can be changed
1570 * by the administrator (or by a user with enough privs). Everytime a user
1571 * wants to print, the devicemode is resetted to the default. In Word, everytime
1572 * you print, the printer's characteristics are always reset to the global devicemode.
1574 * NT 2000:
1575 * -------
1576 * In W2K, there is the notion of per-user devicemode. The first time you use
1577 * a printer, a per-user devicemode is build from the global devicemode.
1578 * If you change your per-user devicemode, it is saved in the registry, under the
1579 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1580 * printer preferences available.
1582 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1583 * on the General Tab of the printer properties windows.
1585 * To change the global devicemode: it's the "Printing Defaults..." button
1586 * on the Advanced Tab of the printer properties window.
1588 * JFM.
1589 ********************************************************************/
1591 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1593 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1594 POLICY_HND *handle = &r_u->handle;
1596 fstring name;
1597 int snum;
1598 struct current_user user;
1599 Printer_entry *Printer=NULL;
1601 if ( !q_u->printername )
1602 return WERR_INVALID_PRINTER_NAME;
1604 /* some sanity check because you can open a printer or a print server */
1605 /* aka: \\server\printer or \\server */
1607 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1609 DEBUGADD(3,("checking name: %s\n",name));
1611 if (!open_printer_hnd(p, handle, name, 0))
1612 return WERR_INVALID_PRINTER_NAME;
1614 Printer=find_printer_index_by_hnd(p, handle);
1615 if ( !Printer ) {
1616 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1617 "handle we created for printer %s\n", name ));
1618 close_printer_handle(p,handle);
1619 return WERR_INVALID_PRINTER_NAME;
1622 get_current_user(&user, p);
1625 * First case: the user is opening the print server:
1627 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1628 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1630 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1631 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1632 * or if the user is listed in the smb.conf printer admin parameter.
1634 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1635 * client view printer folder, but does not show the MSAPW.
1637 * Note: this test needs code to check access rights here too. Jeremy
1638 * could you look at this?
1640 * Second case: the user is opening a printer:
1641 * NT doesn't let us connect to a printer if the connecting user
1642 * doesn't have print permission.
1645 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1647 /* Printserver handles use global struct... */
1649 snum = -1;
1651 /* Map standard access rights to object specific access rights */
1653 se_map_standard(&printer_default->access_required,
1654 &printserver_std_mapping);
1656 /* Deny any object specific bits that don't apply to print
1657 servers (i.e printer and job specific bits) */
1659 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1661 if (printer_default->access_required &
1662 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1663 DEBUG(3, ("access DENIED for non-printserver bits"));
1664 close_printer_handle(p, handle);
1665 return WERR_ACCESS_DENIED;
1668 /* Allow admin access */
1670 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1672 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1674 if (!lp_ms_add_printer_wizard()) {
1675 close_printer_handle(p, handle);
1676 return WERR_ACCESS_DENIED;
1679 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1680 and not a printer admin, then fail */
1682 if ( user.uid != 0
1683 && !user_has_privileges( user.nt_user_token, &se_printop )
1684 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1686 close_printer_handle(p, handle);
1687 return WERR_ACCESS_DENIED;
1690 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1692 else
1694 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1697 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1698 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1700 /* We fall through to return WERR_OK */
1703 else
1705 /* NT doesn't let us connect to a printer if the connecting user
1706 doesn't have print permission. */
1708 if (!get_printer_snum(p, handle, &snum)) {
1709 close_printer_handle(p, handle);
1710 return WERR_BADFID;
1713 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1715 /* map an empty access mask to the minimum access mask */
1716 if (printer_default->access_required == 0x0)
1717 printer_default->access_required = PRINTER_ACCESS_USE;
1720 * If we are not serving the printer driver for this printer,
1721 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1722 * will keep NT clients happy --jerry
1725 if (lp_use_client_driver(snum)
1726 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1728 printer_default->access_required = PRINTER_ACCESS_USE;
1731 /* check smb.conf parameters and the the sec_desc */
1733 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1734 DEBUG(3, ("access DENIED for printer open\n"));
1735 close_printer_handle(p, handle);
1736 return WERR_ACCESS_DENIED;
1739 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1740 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1741 close_printer_handle(p, handle);
1742 return WERR_ACCESS_DENIED;
1745 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1746 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1747 else
1748 printer_default->access_required = PRINTER_ACCESS_USE;
1750 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1751 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1755 Printer->access_granted = printer_default->access_required;
1758 * If the client sent a devmode in the OpenPrinter() call, then
1759 * save it here in case we get a job submission on this handle
1762 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1763 && q_u->printer_default.devmode_cont.devmode_ptr )
1765 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1766 &Printer->nt_devmode );
1769 #if 0 /* JERRY -- I'm doubtful this is really effective */
1770 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1771 optimization in Windows 2000 clients --jerry */
1773 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1774 && (RA_WIN2K == get_remote_arch()) )
1776 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1777 sys_usleep( 500000 );
1779 #endif
1781 return WERR_OK;
1784 /****************************************************************************
1785 ****************************************************************************/
1787 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1788 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1790 BOOL ret = True;
1792 switch (level) {
1793 case 2:
1794 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1795 break;
1796 default:
1797 break;
1800 return ret;
1803 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1804 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1806 BOOL result = True;
1808 switch (level) {
1809 case 3:
1810 printer->info_3=NULL;
1811 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1812 result = False;
1813 break;
1814 case 6:
1815 printer->info_6=NULL;
1816 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1817 result = False;
1818 break;
1819 default:
1820 break;
1823 return result;
1826 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1827 NT_DEVICEMODE **pp_nt_devmode)
1829 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1832 * Ensure nt_devmode is a valid pointer
1833 * as we will be overwriting it.
1836 if (nt_devmode == NULL) {
1837 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1838 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1839 return False;
1842 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1843 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1845 nt_devmode->specversion=devmode->specversion;
1846 nt_devmode->driverversion=devmode->driverversion;
1847 nt_devmode->size=devmode->size;
1848 nt_devmode->fields=devmode->fields;
1849 nt_devmode->orientation=devmode->orientation;
1850 nt_devmode->papersize=devmode->papersize;
1851 nt_devmode->paperlength=devmode->paperlength;
1852 nt_devmode->paperwidth=devmode->paperwidth;
1853 nt_devmode->scale=devmode->scale;
1854 nt_devmode->copies=devmode->copies;
1855 nt_devmode->defaultsource=devmode->defaultsource;
1856 nt_devmode->printquality=devmode->printquality;
1857 nt_devmode->color=devmode->color;
1858 nt_devmode->duplex=devmode->duplex;
1859 nt_devmode->yresolution=devmode->yresolution;
1860 nt_devmode->ttoption=devmode->ttoption;
1861 nt_devmode->collate=devmode->collate;
1863 nt_devmode->logpixels=devmode->logpixels;
1864 nt_devmode->bitsperpel=devmode->bitsperpel;
1865 nt_devmode->pelswidth=devmode->pelswidth;
1866 nt_devmode->pelsheight=devmode->pelsheight;
1867 nt_devmode->displayflags=devmode->displayflags;
1868 nt_devmode->displayfrequency=devmode->displayfrequency;
1869 nt_devmode->icmmethod=devmode->icmmethod;
1870 nt_devmode->icmintent=devmode->icmintent;
1871 nt_devmode->mediatype=devmode->mediatype;
1872 nt_devmode->dithertype=devmode->dithertype;
1873 nt_devmode->reserved1=devmode->reserved1;
1874 nt_devmode->reserved2=devmode->reserved2;
1875 nt_devmode->panningwidth=devmode->panningwidth;
1876 nt_devmode->panningheight=devmode->panningheight;
1879 * Only change private and driverextra if the incoming devmode
1880 * has a new one. JRA.
1883 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1884 SAFE_FREE(nt_devmode->private);
1885 nt_devmode->driverextra=devmode->driverextra;
1886 if((nt_devmode->private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1887 return False;
1888 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1891 *pp_nt_devmode = nt_devmode;
1893 return True;
1896 /********************************************************************
1897 * _spoolss_enddocprinter_internal.
1898 ********************************************************************/
1900 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1902 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1903 int snum;
1905 if (!Printer) {
1906 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1907 return WERR_BADFID;
1910 if (!get_printer_snum(p, handle, &snum))
1911 return WERR_BADFID;
1913 Printer->document_started=False;
1914 print_job_end(snum, Printer->jobid,True);
1915 /* error codes unhandled so far ... */
1917 return WERR_OK;
1920 /********************************************************************
1921 * api_spoolss_closeprinter
1922 ********************************************************************/
1924 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1926 POLICY_HND *handle = &q_u->handle;
1928 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1930 if (Printer && Printer->document_started)
1931 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1933 if (!close_printer_handle(p, handle))
1934 return WERR_BADFID;
1936 /* clear the returned printer handle. Observed behavior
1937 from Win2k server. Don't think this really matters.
1938 Previous code just copied the value of the closed
1939 handle. --jerry */
1941 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1943 return WERR_OK;
1946 /********************************************************************
1947 * api_spoolss_deleteprinter
1949 ********************************************************************/
1951 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1953 POLICY_HND *handle = &q_u->handle;
1954 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1955 WERROR result;
1957 if (Printer && Printer->document_started)
1958 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1960 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1962 result = delete_printer_handle(p, handle);
1964 update_c_setprinter(False);
1966 return result;
1969 /*******************************************************************
1970 * static function to lookup the version id corresponding to an
1971 * long architecture string
1972 ******************************************************************/
1974 static int get_version_id (char * arch)
1976 int i;
1977 struct table_node archi_table[]= {
1979 {"Windows 4.0", "WIN40", 0 },
1980 {"Windows NT x86", "W32X86", 2 },
1981 {"Windows NT R4000", "W32MIPS", 2 },
1982 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1983 {"Windows NT PowerPC", "W32PPC", 2 },
1984 {"Windows IA64", "IA64", 3 },
1985 {"Windows x64", "x64", 3 },
1986 {NULL, "", -1 }
1989 for (i=0; archi_table[i].long_archi != NULL; i++)
1991 if (strcmp(arch, archi_table[i].long_archi) == 0)
1992 return (archi_table[i].version);
1995 return -1;
1998 /********************************************************************
1999 * _spoolss_deleteprinterdriver
2000 ********************************************************************/
2002 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2004 fstring driver;
2005 fstring arch;
2006 NT_PRINTER_DRIVER_INFO_LEVEL info;
2007 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2008 int version;
2009 struct current_user user;
2010 WERROR status;
2011 WERROR status_win2k = WERR_ACCESS_DENIED;
2013 get_current_user(&user, p);
2015 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2016 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2018 /* check that we have a valid driver name first */
2020 if ((version=get_version_id(arch)) == -1)
2021 return WERR_INVALID_ENVIRONMENT;
2023 ZERO_STRUCT(info);
2024 ZERO_STRUCT(info_win2k);
2026 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2028 /* try for Win2k driver if "Windows NT x86" */
2030 if ( version == 2 ) {
2031 version = 3;
2032 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2033 status = WERR_UNKNOWN_PRINTER_DRIVER;
2034 goto done;
2037 /* otherwise it was a failure */
2038 else {
2039 status = WERR_UNKNOWN_PRINTER_DRIVER;
2040 goto done;
2045 if (printer_driver_in_use(info.info_3)) {
2046 status = WERR_PRINTER_DRIVER_IN_USE;
2047 goto done;
2050 if ( version == 2 )
2052 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2054 /* if we get to here, we now have 2 driver info structures to remove */
2055 /* remove the Win2k driver first*/
2057 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2058 free_a_printer_driver( info_win2k, 3 );
2060 /* this should not have failed---if it did, report to client */
2061 if ( !W_ERROR_IS_OK(status_win2k) )
2062 goto done;
2066 status = delete_printer_driver(info.info_3, &user, version, False);
2068 /* if at least one of the deletes succeeded return OK */
2070 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2071 status = WERR_OK;
2073 done:
2074 free_a_printer_driver( info, 3 );
2076 return status;
2079 /********************************************************************
2080 * spoolss_deleteprinterdriverex
2081 ********************************************************************/
2083 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2085 fstring driver;
2086 fstring arch;
2087 NT_PRINTER_DRIVER_INFO_LEVEL info;
2088 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2089 int version;
2090 uint32 flags = q_u->delete_flags;
2091 BOOL delete_files;
2092 struct current_user user;
2093 WERROR status;
2094 WERROR status_win2k = WERR_ACCESS_DENIED;
2096 get_current_user(&user, p);
2098 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2099 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2101 /* check that we have a valid driver name first */
2102 if ((version=get_version_id(arch)) == -1) {
2103 /* this is what NT returns */
2104 return WERR_INVALID_ENVIRONMENT;
2107 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2108 version = q_u->version;
2110 ZERO_STRUCT(info);
2111 ZERO_STRUCT(info_win2k);
2113 status = get_a_printer_driver(&info, 3, driver, arch, version);
2115 if ( !W_ERROR_IS_OK(status) )
2118 * if the client asked for a specific version,
2119 * or this is something other than Windows NT x86,
2120 * then we've failed
2123 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2124 goto done;
2126 /* try for Win2k driver if "Windows NT x86" */
2128 version = 3;
2129 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2130 status = WERR_UNKNOWN_PRINTER_DRIVER;
2131 goto done;
2135 if ( printer_driver_in_use(info.info_3) ) {
2136 status = WERR_PRINTER_DRIVER_IN_USE;
2137 goto done;
2141 * we have a couple of cases to consider.
2142 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2143 * then the delete should fail if **any** files overlap with
2144 * other drivers
2145 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2146 * non-overlapping files
2147 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2148 * is set, the do not delete any files
2149 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2152 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2154 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2156 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2157 /* no idea of the correct error here */
2158 status = WERR_ACCESS_DENIED;
2159 goto done;
2163 /* also check for W32X86/3 if necessary; maybe we already have? */
2165 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2166 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2169 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2170 /* no idea of the correct error here */
2171 free_a_printer_driver( info_win2k, 3 );
2172 status = WERR_ACCESS_DENIED;
2173 goto done;
2176 /* if we get to here, we now have 2 driver info structures to remove */
2177 /* remove the Win2k driver first*/
2179 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2180 free_a_printer_driver( info_win2k, 3 );
2182 /* this should not have failed---if it did, report to client */
2184 if ( !W_ERROR_IS_OK(status_win2k) )
2185 goto done;
2189 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2191 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2192 status = WERR_OK;
2193 done:
2194 free_a_printer_driver( info, 3 );
2196 return status;
2200 /****************************************************************************
2201 Internal routine for retreiving printerdata
2202 ***************************************************************************/
2204 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2205 const char *key, const char *value, uint32 *type, uint8 **data,
2206 uint32 *needed, uint32 in_size )
2208 REGISTRY_VALUE *val;
2209 int size, data_len;
2211 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2212 return WERR_BADFILE;
2214 *type = regval_type( val );
2216 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2218 size = regval_size( val );
2220 /* copy the min(in_size, len) */
2222 if ( in_size ) {
2223 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2225 /* special case for 0 length values */
2226 if ( data_len ) {
2227 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2228 return WERR_NOMEM;
2230 else {
2231 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2232 return WERR_NOMEM;
2235 else
2236 *data = NULL;
2238 *needed = size;
2240 DEBUG(5,("get_printer_dataex: copy done\n"));
2242 return WERR_OK;
2245 /****************************************************************************
2246 Internal routine for removing printerdata
2247 ***************************************************************************/
2249 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2251 return delete_printer_data( printer->info_2, key, value );
2254 /****************************************************************************
2255 Internal routine for storing printerdata
2256 ***************************************************************************/
2258 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2259 uint32 type, uint8 *data, int real_len )
2261 delete_printer_data( printer->info_2, key, value );
2263 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2266 /********************************************************************
2267 GetPrinterData on a printer server Handle.
2268 ********************************************************************/
2270 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2272 int i;
2274 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2276 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2277 *type = REG_DWORD;
2278 if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
2279 return WERR_NOMEM;
2280 *needed = 0x4;
2281 return WERR_OK;
2284 if (!StrCaseCmp(value, "BeepEnabled")) {
2285 *type = REG_DWORD;
2286 if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
2287 return WERR_NOMEM;
2288 SIVAL(*data, 0, 0x00);
2289 *needed = 0x4;
2290 return WERR_OK;
2293 if (!StrCaseCmp(value, "EventLog")) {
2294 *type = REG_DWORD;
2295 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2296 return WERR_NOMEM;
2297 /* formally was 0x1b */
2298 SIVAL(*data, 0, 0x0);
2299 *needed = 0x4;
2300 return WERR_OK;
2303 if (!StrCaseCmp(value, "NetPopup")) {
2304 *type = REG_DWORD;
2305 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2306 return WERR_NOMEM;
2307 SIVAL(*data, 0, 0x00);
2308 *needed = 0x4;
2309 return WERR_OK;
2312 if (!StrCaseCmp(value, "MajorVersion")) {
2313 *type = REG_DWORD;
2314 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2315 return WERR_NOMEM;
2317 /* Windows NT 4.0 seems to not allow uploading of drivers
2318 to a server that reports 0x3 as the MajorVersion.
2319 need to investigate more how Win2k gets around this .
2320 -- jerry */
2322 if ( RA_WINNT == get_remote_arch() )
2323 SIVAL(*data, 0, 2);
2324 else
2325 SIVAL(*data, 0, 3);
2327 *needed = 0x4;
2328 return WERR_OK;
2331 if (!StrCaseCmp(value, "MinorVersion")) {
2332 *type = REG_DWORD;
2333 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2334 return WERR_NOMEM;
2335 SIVAL(*data, 0, 0);
2336 *needed = 0x4;
2337 return WERR_OK;
2340 /* REG_BINARY
2341 * uint32 size = 0x114
2342 * uint32 major = 5
2343 * uint32 minor = [0|1]
2344 * uint32 build = [2195|2600]
2345 * extra unicode string = e.g. "Service Pack 3"
2347 if (!StrCaseCmp(value, "OSVersion")) {
2348 *type = REG_BINARY;
2349 *needed = 0x114;
2351 if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
2352 return WERR_NOMEM;
2353 ZERO_STRUCTP( *data );
2355 SIVAL(*data, 0, *needed); /* size */
2356 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2357 SIVAL(*data, 8, 0);
2358 SIVAL(*data, 12, 2195); /* build */
2360 /* leave extra string empty */
2362 return WERR_OK;
2366 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2367 const char *string="C:\\PRINTERS";
2368 *type = REG_SZ;
2369 *needed = 2*(strlen(string)+1);
2370 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2371 return WERR_NOMEM;
2372 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2374 /* it's done by hand ready to go on the wire */
2375 for (i=0; i<strlen(string); i++) {
2376 (*data)[2*i]=string[i];
2377 (*data)[2*i+1]='\0';
2379 return WERR_OK;
2382 if (!StrCaseCmp(value, "Architecture")) {
2383 const char *string="Windows NT x86";
2384 *type = REG_SZ;
2385 *needed = 2*(strlen(string)+1);
2386 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2387 return WERR_NOMEM;
2388 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 for (i=0; i<strlen(string); i++) {
2390 (*data)[2*i]=string[i];
2391 (*data)[2*i+1]='\0';
2393 return WERR_OK;
2396 if (!StrCaseCmp(value, "DsPresent")) {
2397 *type = REG_DWORD;
2398 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2399 return WERR_NOMEM;
2401 /* only show the publish check box if we are a
2402 memeber of a AD domain */
2404 if ( lp_security() == SEC_ADS )
2405 SIVAL(*data, 0, 0x01);
2406 else
2407 SIVAL(*data, 0, 0x00);
2409 *needed = 0x4;
2410 return WERR_OK;
2413 if (!StrCaseCmp(value, "DNSMachineName")) {
2414 pstring hostname;
2416 if (!get_mydnsfullname(hostname))
2417 return WERR_BADFILE;
2418 *type = REG_SZ;
2419 *needed = 2*(strlen(hostname)+1);
2420 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2421 return WERR_NOMEM;
2422 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2423 for (i=0; i<strlen(hostname); i++) {
2424 (*data)[2*i]=hostname[i];
2425 (*data)[2*i+1]='\0';
2427 return WERR_OK;
2431 return WERR_BADFILE;
2434 /********************************************************************
2435 * spoolss_getprinterdata
2436 ********************************************************************/
2438 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2440 POLICY_HND *handle = &q_u->handle;
2441 UNISTR2 *valuename = &q_u->valuename;
2442 uint32 in_size = q_u->size;
2443 uint32 *type = &r_u->type;
2444 uint32 *out_size = &r_u->size;
2445 uint8 **data = &r_u->data;
2446 uint32 *needed = &r_u->needed;
2447 WERROR status;
2448 fstring value;
2449 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2450 NT_PRINTER_INFO_LEVEL *printer = NULL;
2451 int snum = 0;
2454 * Reminder: when it's a string, the length is in BYTES
2455 * even if UNICODE is negociated.
2457 * JFM, 4/19/1999
2460 *out_size = in_size;
2462 /* in case of problem, return some default values */
2464 *needed = 0;
2465 *type = 0;
2467 DEBUG(4,("_spoolss_getprinterdata\n"));
2469 if ( !Printer ) {
2470 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2471 status = WERR_BADFID;
2472 goto done;
2475 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2477 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2478 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2479 else
2481 if ( !get_printer_snum(p,handle, &snum) ) {
2482 status = WERR_BADFID;
2483 goto done;
2486 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2487 if ( !W_ERROR_IS_OK(status) )
2488 goto done;
2490 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2492 if ( strequal(value, "ChangeId") ) {
2493 *type = REG_DWORD;
2494 *needed = sizeof(uint32);
2495 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2496 status = WERR_NOMEM;
2497 goto done;
2499 SIVAL( *data, 0, printer->info_2->changeid );
2500 status = WERR_OK;
2502 else
2503 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2506 if (*needed > *out_size)
2507 status = WERR_MORE_DATA;
2509 done:
2510 if ( !W_ERROR_IS_OK(status) )
2512 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2514 /* reply this param doesn't exist */
2516 if ( *out_size ) {
2517 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2518 if ( printer )
2519 free_a_printer( &printer, 2 );
2520 return WERR_NOMEM;
2523 else {
2524 *data = NULL;
2528 /* cleanup & exit */
2530 if ( printer )
2531 free_a_printer( &printer, 2 );
2533 return status;
2536 /*********************************************************
2537 Connect to the client machine.
2538 **********************************************************/
2540 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2541 struct in_addr *client_ip, const char *remote_machine)
2543 ZERO_STRUCTP(the_cli);
2545 if(cli_initialise(the_cli) == NULL) {
2546 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2547 return False;
2550 if ( is_zero_ip(*client_ip) ) {
2551 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2552 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2553 cli_shutdown(the_cli);
2554 return False;
2557 if (ismyip(the_cli->dest_ip)) {
2558 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2559 cli_shutdown(the_cli);
2560 return False;
2563 else {
2564 the_cli->dest_ip.s_addr = client_ip->s_addr;
2565 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2566 inet_ntoa(*client_ip) ));
2569 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2570 DEBUG(0,("spoolss_connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2571 cli_shutdown(the_cli);
2572 return False;
2575 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2576 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2577 remote_machine));
2578 cli_shutdown(the_cli);
2579 return False;
2582 the_cli->protocol = PROTOCOL_NT1;
2583 cli_setup_signing_state(the_cli, lp_client_signing());
2585 if (!cli_negprot(the_cli)) {
2586 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2587 cli_shutdown(the_cli);
2588 return False;
2591 if (the_cli->protocol != PROTOCOL_NT1) {
2592 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2593 cli_shutdown(the_cli);
2594 return False;
2598 * Do an anonymous session setup.
2601 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2602 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2603 cli_shutdown(the_cli);
2604 return False;
2607 if (!(the_cli->sec_mode & 1)) {
2608 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2609 cli_shutdown(the_cli);
2610 return False;
2613 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2614 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2615 cli_shutdown(the_cli);
2616 return False;
2620 * Ok - we have an anonymous connection to the IPC$ share.
2621 * Now start the NT Domain stuff :-).
2624 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2625 DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2626 cli_nt_session_close(the_cli);
2627 cli_ulogoff(the_cli);
2628 cli_shutdown(the_cli);
2629 return False;
2632 return True;
2635 /***************************************************************************
2636 Connect to the client.
2637 ****************************************************************************/
2639 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2640 uint32 localprinter, uint32 type,
2641 POLICY_HND *handle, struct in_addr *client_ip)
2643 WERROR result;
2646 * If it's the first connection, contact the client
2647 * and connect to the IPC$ share anonymously
2649 if (smb_connections==0) {
2650 fstring unix_printer;
2652 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2654 ZERO_STRUCT(notify_cli);
2656 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2657 return False;
2659 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2660 /* Tell the connections db we're now interested in printer
2661 * notify messages. */
2662 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2666 * Tell the specific printing tdb we want messages for this printer
2667 * by registering our PID.
2670 if (!print_notify_register_pid(snum))
2671 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2673 smb_connections++;
2675 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2676 type, handle);
2678 if (!W_ERROR_IS_OK(result))
2679 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2680 dos_errstr(result)));
2682 return (W_ERROR_IS_OK(result));
2685 /********************************************************************
2686 * _spoolss_rffpcnex
2687 * ReplyFindFirstPrinterChangeNotifyEx
2689 * before replying OK: status=0 a rpc call is made to the workstation
2690 * asking ReplyOpenPrinter
2692 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2693 * called from api_spoolss_rffpcnex
2694 ********************************************************************/
2696 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2698 POLICY_HND *handle = &q_u->handle;
2699 uint32 flags = q_u->flags;
2700 uint32 options = q_u->options;
2701 UNISTR2 *localmachine = &q_u->localmachine;
2702 uint32 printerlocal = q_u->printerlocal;
2703 int snum = -1;
2704 SPOOL_NOTIFY_OPTION *option = q_u->option;
2705 struct in_addr client_ip;
2707 /* store the notify value in the printer struct */
2709 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2711 if (!Printer) {
2712 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2713 return WERR_BADFID;
2716 Printer->notify.flags=flags;
2717 Printer->notify.options=options;
2718 Printer->notify.printerlocal=printerlocal;
2720 if (Printer->notify.option)
2721 free_spool_notify_option(&Printer->notify.option);
2723 Printer->notify.option=dup_spool_notify_option(option);
2725 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2726 sizeof(Printer->notify.localmachine)-1);
2728 /* Connect to the client machine and send a ReplyOpenPrinter */
2730 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2731 snum = -1;
2732 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2733 !get_printer_snum(p, handle, &snum) )
2734 return WERR_BADFID;
2736 client_ip.s_addr = inet_addr(p->conn->client_address);
2738 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2739 Printer->notify.printerlocal, 1,
2740 &Printer->notify.client_hnd, &client_ip))
2741 return WERR_SERVER_UNAVAILABLE;
2743 Printer->notify.client_connected=True;
2745 return WERR_OK;
2748 /*******************************************************************
2749 * fill a notify_info_data with the servername
2750 ********************************************************************/
2752 void spoolss_notify_server_name(int snum,
2753 SPOOL_NOTIFY_INFO_DATA *data,
2754 print_queue_struct *queue,
2755 NT_PRINTER_INFO_LEVEL *printer,
2756 TALLOC_CTX *mem_ctx)
2758 pstring temp;
2759 uint32 len;
2761 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2763 data->notify_data.data.length = len;
2764 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2766 if (!data->notify_data.data.string) {
2767 data->notify_data.data.length = 0;
2768 return;
2771 memcpy(data->notify_data.data.string, temp, len);
2774 /*******************************************************************
2775 * fill a notify_info_data with the printername (not including the servername).
2776 ********************************************************************/
2778 void spoolss_notify_printer_name(int snum,
2779 SPOOL_NOTIFY_INFO_DATA *data,
2780 print_queue_struct *queue,
2781 NT_PRINTER_INFO_LEVEL *printer,
2782 TALLOC_CTX *mem_ctx)
2784 pstring temp;
2785 uint32 len;
2787 /* the notify name should not contain the \\server\ part */
2788 char *p = strrchr(printer->info_2->printername, '\\');
2790 if (!p) {
2791 p = printer->info_2->printername;
2792 } else {
2793 p++;
2796 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2798 data->notify_data.data.length = len;
2799 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2801 if (!data->notify_data.data.string) {
2802 data->notify_data.data.length = 0;
2803 return;
2806 memcpy(data->notify_data.data.string, temp, len);
2809 /*******************************************************************
2810 * fill a notify_info_data with the servicename
2811 ********************************************************************/
2813 void spoolss_notify_share_name(int snum,
2814 SPOOL_NOTIFY_INFO_DATA *data,
2815 print_queue_struct *queue,
2816 NT_PRINTER_INFO_LEVEL *printer,
2817 TALLOC_CTX *mem_ctx)
2819 pstring temp;
2820 uint32 len;
2822 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2824 data->notify_data.data.length = len;
2825 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2827 if (!data->notify_data.data.string) {
2828 data->notify_data.data.length = 0;
2829 return;
2832 memcpy(data->notify_data.data.string, temp, len);
2835 /*******************************************************************
2836 * fill a notify_info_data with the port name
2837 ********************************************************************/
2839 void spoolss_notify_port_name(int snum,
2840 SPOOL_NOTIFY_INFO_DATA *data,
2841 print_queue_struct *queue,
2842 NT_PRINTER_INFO_LEVEL *printer,
2843 TALLOC_CTX *mem_ctx)
2845 pstring temp;
2846 uint32 len;
2848 /* even if it's strange, that's consistant in all the code */
2850 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2852 data->notify_data.data.length = len;
2853 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2855 if (!data->notify_data.data.string) {
2856 data->notify_data.data.length = 0;
2857 return;
2860 memcpy(data->notify_data.data.string, temp, len);
2863 /*******************************************************************
2864 * fill a notify_info_data with the printername
2865 * but it doesn't exist, have to see what to do
2866 ********************************************************************/
2868 void spoolss_notify_driver_name(int snum,
2869 SPOOL_NOTIFY_INFO_DATA *data,
2870 print_queue_struct *queue,
2871 NT_PRINTER_INFO_LEVEL *printer,
2872 TALLOC_CTX *mem_ctx)
2874 pstring temp;
2875 uint32 len;
2877 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2879 data->notify_data.data.length = len;
2880 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2882 if (!data->notify_data.data.string) {
2883 data->notify_data.data.length = 0;
2884 return;
2887 memcpy(data->notify_data.data.string, temp, len);
2890 /*******************************************************************
2891 * fill a notify_info_data with the comment
2892 ********************************************************************/
2894 void spoolss_notify_comment(int snum,
2895 SPOOL_NOTIFY_INFO_DATA *data,
2896 print_queue_struct *queue,
2897 NT_PRINTER_INFO_LEVEL *printer,
2898 TALLOC_CTX *mem_ctx)
2900 pstring temp;
2901 uint32 len;
2903 if (*printer->info_2->comment == '\0')
2904 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2905 else
2906 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2908 data->notify_data.data.length = len;
2909 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2911 if (!data->notify_data.data.string) {
2912 data->notify_data.data.length = 0;
2913 return;
2916 memcpy(data->notify_data.data.string, temp, len);
2919 /*******************************************************************
2920 * fill a notify_info_data with the comment
2921 * location = "Room 1, floor 2, building 3"
2922 ********************************************************************/
2924 void spoolss_notify_location(int snum,
2925 SPOOL_NOTIFY_INFO_DATA *data,
2926 print_queue_struct *queue,
2927 NT_PRINTER_INFO_LEVEL *printer,
2928 TALLOC_CTX *mem_ctx)
2930 pstring temp;
2931 uint32 len;
2933 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2935 data->notify_data.data.length = len;
2936 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2938 if (!data->notify_data.data.string) {
2939 data->notify_data.data.length = 0;
2940 return;
2943 memcpy(data->notify_data.data.string, temp, len);
2946 /*******************************************************************
2947 * fill a notify_info_data with the device mode
2948 * jfm:xxxx don't to it for know but that's a real problem !!!
2949 ********************************************************************/
2951 static void spoolss_notify_devmode(int snum,
2952 SPOOL_NOTIFY_INFO_DATA *data,
2953 print_queue_struct *queue,
2954 NT_PRINTER_INFO_LEVEL *printer,
2955 TALLOC_CTX *mem_ctx)
2959 /*******************************************************************
2960 * fill a notify_info_data with the separator file name
2961 ********************************************************************/
2963 void spoolss_notify_sepfile(int snum,
2964 SPOOL_NOTIFY_INFO_DATA *data,
2965 print_queue_struct *queue,
2966 NT_PRINTER_INFO_LEVEL *printer,
2967 TALLOC_CTX *mem_ctx)
2969 pstring temp;
2970 uint32 len;
2972 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2974 data->notify_data.data.length = len;
2975 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2977 if (!data->notify_data.data.string) {
2978 data->notify_data.data.length = 0;
2979 return;
2982 memcpy(data->notify_data.data.string, temp, len);
2985 /*******************************************************************
2986 * fill a notify_info_data with the print processor
2987 * jfm:xxxx return always winprint to indicate we don't do anything to it
2988 ********************************************************************/
2990 void spoolss_notify_print_processor(int snum,
2991 SPOOL_NOTIFY_INFO_DATA *data,
2992 print_queue_struct *queue,
2993 NT_PRINTER_INFO_LEVEL *printer,
2994 TALLOC_CTX *mem_ctx)
2996 pstring temp;
2997 uint32 len;
2999 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3001 data->notify_data.data.length = len;
3002 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3004 if (!data->notify_data.data.string) {
3005 data->notify_data.data.length = 0;
3006 return;
3009 memcpy(data->notify_data.data.string, temp, len);
3012 /*******************************************************************
3013 * fill a notify_info_data with the print processor options
3014 * jfm:xxxx send an empty string
3015 ********************************************************************/
3017 void spoolss_notify_parameters(int snum,
3018 SPOOL_NOTIFY_INFO_DATA *data,
3019 print_queue_struct *queue,
3020 NT_PRINTER_INFO_LEVEL *printer,
3021 TALLOC_CTX *mem_ctx)
3023 pstring temp;
3024 uint32 len;
3026 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3028 data->notify_data.data.length = len;
3029 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3031 if (!data->notify_data.data.string) {
3032 data->notify_data.data.length = 0;
3033 return;
3036 memcpy(data->notify_data.data.string, temp, len);
3039 /*******************************************************************
3040 * fill a notify_info_data with the data type
3041 * jfm:xxxx always send RAW as data type
3042 ********************************************************************/
3044 void spoolss_notify_datatype(int snum,
3045 SPOOL_NOTIFY_INFO_DATA *data,
3046 print_queue_struct *queue,
3047 NT_PRINTER_INFO_LEVEL *printer,
3048 TALLOC_CTX *mem_ctx)
3050 pstring temp;
3051 uint32 len;
3053 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3055 data->notify_data.data.length = len;
3056 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3058 if (!data->notify_data.data.string) {
3059 data->notify_data.data.length = 0;
3060 return;
3063 memcpy(data->notify_data.data.string, temp, len);
3066 /*******************************************************************
3067 * fill a notify_info_data with the security descriptor
3068 * jfm:xxxx send an null pointer to say no security desc
3069 * have to implement security before !
3070 ********************************************************************/
3072 static void spoolss_notify_security_desc(int snum,
3073 SPOOL_NOTIFY_INFO_DATA *data,
3074 print_queue_struct *queue,
3075 NT_PRINTER_INFO_LEVEL *printer,
3076 TALLOC_CTX *mem_ctx)
3078 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3079 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3082 /*******************************************************************
3083 * fill a notify_info_data with the attributes
3084 * jfm:xxxx a samba printer is always shared
3085 ********************************************************************/
3087 void spoolss_notify_attributes(int snum,
3088 SPOOL_NOTIFY_INFO_DATA *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3093 data->notify_data.value[0] = printer->info_2->attributes;
3094 data->notify_data.value[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the priority
3099 ********************************************************************/
3101 static void spoolss_notify_priority(int snum,
3102 SPOOL_NOTIFY_INFO_DATA *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 data->notify_data.value[0] = printer->info_2->priority;
3108 data->notify_data.value[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the default priority
3113 ********************************************************************/
3115 static void spoolss_notify_default_priority(int snum,
3116 SPOOL_NOTIFY_INFO_DATA *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 data->notify_data.value[0] = printer->info_2->default_priority;
3122 data->notify_data.value[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the start time
3127 ********************************************************************/
3129 static void spoolss_notify_start_time(int snum,
3130 SPOOL_NOTIFY_INFO_DATA *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3135 data->notify_data.value[0] = printer->info_2->starttime;
3136 data->notify_data.value[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the until time
3141 ********************************************************************/
3143 static void spoolss_notify_until_time(int snum,
3144 SPOOL_NOTIFY_INFO_DATA *data,
3145 print_queue_struct *queue,
3146 NT_PRINTER_INFO_LEVEL *printer,
3147 TALLOC_CTX *mem_ctx)
3149 data->notify_data.value[0] = printer->info_2->untiltime;
3150 data->notify_data.value[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the status
3155 ********************************************************************/
3157 static void spoolss_notify_status(int snum,
3158 SPOOL_NOTIFY_INFO_DATA *data,
3159 print_queue_struct *queue,
3160 NT_PRINTER_INFO_LEVEL *printer,
3161 TALLOC_CTX *mem_ctx)
3163 print_status_struct status;
3165 print_queue_length(snum, &status);
3166 data->notify_data.value[0]=(uint32) status.status;
3167 data->notify_data.value[1] = 0;
3170 /*******************************************************************
3171 * fill a notify_info_data with the number of jobs queued
3172 ********************************************************************/
3174 void spoolss_notify_cjobs(int snum,
3175 SPOOL_NOTIFY_INFO_DATA *data,
3176 print_queue_struct *queue,
3177 NT_PRINTER_INFO_LEVEL *printer,
3178 TALLOC_CTX *mem_ctx)
3180 data->notify_data.value[0] = print_queue_length(snum, NULL);
3181 data->notify_data.value[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with the average ppm
3186 ********************************************************************/
3188 static void spoolss_notify_average_ppm(int snum,
3189 SPOOL_NOTIFY_INFO_DATA *data,
3190 print_queue_struct *queue,
3191 NT_PRINTER_INFO_LEVEL *printer,
3192 TALLOC_CTX *mem_ctx)
3194 /* always respond 8 pages per minutes */
3195 /* a little hard ! */
3196 data->notify_data.value[0] = printer->info_2->averageppm;
3197 data->notify_data.value[1] = 0;
3200 /*******************************************************************
3201 * fill a notify_info_data with username
3202 ********************************************************************/
3204 static void spoolss_notify_username(int snum,
3205 SPOOL_NOTIFY_INFO_DATA *data,
3206 print_queue_struct *queue,
3207 NT_PRINTER_INFO_LEVEL *printer,
3208 TALLOC_CTX *mem_ctx)
3210 pstring temp;
3211 uint32 len;
3213 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3215 data->notify_data.data.length = len;
3216 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3218 if (!data->notify_data.data.string) {
3219 data->notify_data.data.length = 0;
3220 return;
3223 memcpy(data->notify_data.data.string, temp, len);
3226 /*******************************************************************
3227 * fill a notify_info_data with job status
3228 ********************************************************************/
3230 static void spoolss_notify_job_status(int snum,
3231 SPOOL_NOTIFY_INFO_DATA *data,
3232 print_queue_struct *queue,
3233 NT_PRINTER_INFO_LEVEL *printer,
3234 TALLOC_CTX *mem_ctx)
3236 data->notify_data.value[0]=nt_printj_status(queue->status);
3237 data->notify_data.value[1] = 0;
3240 /*******************************************************************
3241 * fill a notify_info_data with job name
3242 ********************************************************************/
3244 static void spoolss_notify_job_name(int snum,
3245 SPOOL_NOTIFY_INFO_DATA *data,
3246 print_queue_struct *queue,
3247 NT_PRINTER_INFO_LEVEL *printer,
3248 TALLOC_CTX *mem_ctx)
3250 pstring temp;
3251 uint32 len;
3253 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3255 data->notify_data.data.length = len;
3256 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3258 if (!data->notify_data.data.string) {
3259 data->notify_data.data.length = 0;
3260 return;
3263 memcpy(data->notify_data.data.string, temp, len);
3266 /*******************************************************************
3267 * fill a notify_info_data with job status
3268 ********************************************************************/
3270 static void spoolss_notify_job_status_string(int snum,
3271 SPOOL_NOTIFY_INFO_DATA *data,
3272 print_queue_struct *queue,
3273 NT_PRINTER_INFO_LEVEL *printer,
3274 TALLOC_CTX *mem_ctx)
3277 * Now we're returning job status codes we just return a "" here. JRA.
3280 const char *p = "";
3281 pstring temp;
3282 uint32 len;
3284 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3285 p = "unknown";
3287 switch (queue->status) {
3288 case LPQ_QUEUED:
3289 p = "Queued";
3290 break;
3291 case LPQ_PAUSED:
3292 p = ""; /* NT provides the paused string */
3293 break;
3294 case LPQ_SPOOLING:
3295 p = "Spooling";
3296 break;
3297 case LPQ_PRINTING:
3298 p = "Printing";
3299 break;
3301 #endif /* NO LONGER NEEDED. */
3303 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3305 data->notify_data.data.length = len;
3306 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3308 if (!data->notify_data.data.string) {
3309 data->notify_data.data.length = 0;
3310 return;
3313 memcpy(data->notify_data.data.string, temp, len);
3316 /*******************************************************************
3317 * fill a notify_info_data with job time
3318 ********************************************************************/
3320 static void spoolss_notify_job_time(int snum,
3321 SPOOL_NOTIFY_INFO_DATA *data,
3322 print_queue_struct *queue,
3323 NT_PRINTER_INFO_LEVEL *printer,
3324 TALLOC_CTX *mem_ctx)
3326 data->notify_data.value[0]=0x0;
3327 data->notify_data.value[1]=0;
3330 /*******************************************************************
3331 * fill a notify_info_data with job size
3332 ********************************************************************/
3334 static void spoolss_notify_job_size(int snum,
3335 SPOOL_NOTIFY_INFO_DATA *data,
3336 print_queue_struct *queue,
3337 NT_PRINTER_INFO_LEVEL *printer,
3338 TALLOC_CTX *mem_ctx)
3340 data->notify_data.value[0]=queue->size;
3341 data->notify_data.value[1]=0;
3344 /*******************************************************************
3345 * fill a notify_info_data with page info
3346 ********************************************************************/
3347 static void spoolss_notify_total_pages(int snum,
3348 SPOOL_NOTIFY_INFO_DATA *data,
3349 print_queue_struct *queue,
3350 NT_PRINTER_INFO_LEVEL *printer,
3351 TALLOC_CTX *mem_ctx)
3353 data->notify_data.value[0]=queue->page_count;
3354 data->notify_data.value[1]=0;
3357 /*******************************************************************
3358 * fill a notify_info_data with pages printed info.
3359 ********************************************************************/
3360 static void spoolss_notify_pages_printed(int snum,
3361 SPOOL_NOTIFY_INFO_DATA *data,
3362 print_queue_struct *queue,
3363 NT_PRINTER_INFO_LEVEL *printer,
3364 TALLOC_CTX *mem_ctx)
3366 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3367 data->notify_data.value[1]=0;
3370 /*******************************************************************
3371 Fill a notify_info_data with job position.
3372 ********************************************************************/
3374 static void spoolss_notify_job_position(int snum,
3375 SPOOL_NOTIFY_INFO_DATA *data,
3376 print_queue_struct *queue,
3377 NT_PRINTER_INFO_LEVEL *printer,
3378 TALLOC_CTX *mem_ctx)
3380 data->notify_data.value[0]=queue->job;
3381 data->notify_data.value[1]=0;
3384 /*******************************************************************
3385 Fill a notify_info_data with submitted time.
3386 ********************************************************************/
3388 static void spoolss_notify_submitted_time(int snum,
3389 SPOOL_NOTIFY_INFO_DATA *data,
3390 print_queue_struct *queue,
3391 NT_PRINTER_INFO_LEVEL *printer,
3392 TALLOC_CTX *mem_ctx)
3394 struct tm *t;
3395 uint32 len;
3396 SYSTEMTIME st;
3397 char *p;
3399 t=gmtime(&queue->time);
3401 len = sizeof(SYSTEMTIME);
3403 data->notify_data.data.length = len;
3404 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3406 if (!data->notify_data.data.string) {
3407 data->notify_data.data.length = 0;
3408 return;
3411 make_systemtime(&st, t);
3414 * Systemtime must be linearized as a set of UINT16's.
3415 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3418 p = (char *)data->notify_data.data.string;
3419 SSVAL(p, 0, st.year);
3420 SSVAL(p, 2, st.month);
3421 SSVAL(p, 4, st.dayofweek);
3422 SSVAL(p, 6, st.day);
3423 SSVAL(p, 8, st.hour);
3424 SSVAL(p, 10, st.minute);
3425 SSVAL(p, 12, st.second);
3426 SSVAL(p, 14, st.milliseconds);
3429 struct s_notify_info_data_table
3431 uint16 type;
3432 uint16 field;
3433 const char *name;
3434 uint32 size;
3435 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3436 print_queue_struct *queue,
3437 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3440 /* A table describing the various print notification constants and
3441 whether the notification data is a pointer to a variable sized
3442 buffer, a one value uint32 or a two value uint32. */
3444 static const struct s_notify_info_data_table notify_info_data_table[] =
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3495 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3498 /*******************************************************************
3499 Return the size of info_data structure.
3500 ********************************************************************/
3502 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3504 int i=0;
3506 for (i = 0; i < sizeof(notify_info_data_table); i++)
3508 if ( (notify_info_data_table[i].type == type)
3509 && (notify_info_data_table[i].field == field) )
3511 switch(notify_info_data_table[i].size)
3513 case NOTIFY_ONE_VALUE:
3514 case NOTIFY_TWO_VALUE:
3515 return 1;
3516 case NOTIFY_STRING:
3517 return 2;
3519 /* The only pointer notify data I have seen on
3520 the wire is the submitted time and this has
3521 the notify size set to 4. -tpot */
3523 case NOTIFY_POINTER:
3524 return 4;
3526 case NOTIFY_SECDESC:
3527 return 5;
3532 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3534 return 0;
3537 /*******************************************************************
3538 Return the type of notify_info_data.
3539 ********************************************************************/
3541 static int type_of_notify_info_data(uint16 type, uint16 field)
3543 int i=0;
3545 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3546 if (notify_info_data_table[i].type == type &&
3547 notify_info_data_table[i].field == field)
3548 return notify_info_data_table[i].size;
3551 return False;
3554 /****************************************************************************
3555 ****************************************************************************/
3557 static int search_notify(uint16 type, uint16 field, int *value)
3559 int i;
3561 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3562 if (notify_info_data_table[i].type == type &&
3563 notify_info_data_table[i].field == field &&
3564 notify_info_data_table[i].fn != NULL) {
3565 *value = i;
3566 return True;
3570 return False;
3573 /****************************************************************************
3574 ****************************************************************************/
3576 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3578 info_data->type = type;
3579 info_data->field = field;
3580 info_data->reserved = 0;
3582 info_data->size = size_of_notify_info_data(type, field);
3583 info_data->enc_type = type_of_notify_info_data(type, field);
3585 info_data->id = id;
3590 /*******************************************************************
3592 * fill a notify_info struct with info asked
3594 ********************************************************************/
3596 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3597 snum, SPOOL_NOTIFY_OPTION_TYPE
3598 *option_type, uint32 id,
3599 TALLOC_CTX *mem_ctx)
3601 int field_num,j;
3602 uint16 type;
3603 uint16 field;
3605 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3606 NT_PRINTER_INFO_LEVEL *printer = NULL;
3607 print_queue_struct *queue=NULL;
3609 type=option_type->type;
3611 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3612 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3613 option_type->count, lp_servicename(snum)));
3615 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3616 return False;
3618 for(field_num=0; field_num<option_type->count; field_num++) {
3619 field = option_type->fields[field_num];
3621 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3623 if (!search_notify(type, field, &j) )
3624 continue;
3626 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3627 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3628 return False;
3629 } else
3630 info->data = tid;
3632 current_data = &info->data[info->count];
3634 construct_info_data(current_data, type, field, id);
3636 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3637 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3639 notify_info_data_table[j].fn(snum, current_data, queue,
3640 printer, mem_ctx);
3642 info->count++;
3645 free_a_printer(&printer, 2);
3646 return True;
3649 /*******************************************************************
3651 * fill a notify_info struct with info asked
3653 ********************************************************************/
3655 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3656 SPOOL_NOTIFY_INFO *info,
3657 NT_PRINTER_INFO_LEVEL *printer,
3658 int snum, SPOOL_NOTIFY_OPTION_TYPE
3659 *option_type, uint32 id,
3660 TALLOC_CTX *mem_ctx)
3662 int field_num,j;
3663 uint16 type;
3664 uint16 field;
3666 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3668 DEBUG(4,("construct_notify_jobs_info\n"));
3670 type = option_type->type;
3672 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3673 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3674 option_type->count));
3676 for(field_num=0; field_num<option_type->count; field_num++) {
3677 field = option_type->fields[field_num];
3679 if (!search_notify(type, field, &j) )
3680 continue;
3682 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3683 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3684 return False;
3686 else info->data = tid;
3688 current_data=&(info->data[info->count]);
3690 construct_info_data(current_data, type, field, id);
3691 notify_info_data_table[j].fn(snum, current_data, queue,
3692 printer, mem_ctx);
3693 info->count++;
3696 return True;
3700 * JFM: The enumeration is not that simple, it's even non obvious.
3702 * let's take an example: I want to monitor the PRINTER SERVER for
3703 * the printer's name and the number of jobs currently queued.
3704 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3705 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3707 * I have 3 printers on the back of my server.
3709 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3710 * structures.
3711 * Number Data Id
3712 * 1 printer 1 name 1
3713 * 2 printer 1 cjob 1
3714 * 3 printer 2 name 2
3715 * 4 printer 2 cjob 2
3716 * 5 printer 3 name 3
3717 * 6 printer 3 name 3
3719 * that's the print server case, the printer case is even worse.
3722 /*******************************************************************
3724 * enumerate all printers on the printserver
3725 * fill a notify_info struct with info asked
3727 ********************************************************************/
3729 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3730 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 n_services=lp_numservices();
3736 int i;
3737 SPOOL_NOTIFY_OPTION *option;
3738 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3740 DEBUG(4,("printserver_notify_info\n"));
3742 if (!Printer)
3743 return WERR_BADFID;
3745 option=Printer->notify.option;
3746 info->version=2;
3747 info->data=NULL;
3748 info->count=0;
3750 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3751 sending a ffpcn() request first */
3753 if ( !option )
3754 return WERR_BADFID;
3756 for (i=0; i<option->count; i++) {
3757 option_type=&(option->ctr.type[i]);
3759 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3760 continue;
3762 for (snum=0; snum<n_services; snum++)
3764 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3765 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3769 #if 0
3771 * Debugging information, don't delete.
3774 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3775 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3776 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3778 for (i=0; i<info->count; i++) {
3779 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3780 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3781 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3783 #endif
3785 return WERR_OK;
3788 /*******************************************************************
3790 * fill a notify_info struct with info asked
3792 ********************************************************************/
3794 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3795 TALLOC_CTX *mem_ctx)
3797 int snum;
3798 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3799 int i;
3800 uint32 id;
3801 SPOOL_NOTIFY_OPTION *option;
3802 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3803 int count,j;
3804 print_queue_struct *queue=NULL;
3805 print_status_struct status;
3807 DEBUG(4,("printer_notify_info\n"));
3809 if (!Printer)
3810 return WERR_BADFID;
3812 option=Printer->notify.option;
3813 id = 0x0;
3814 info->version=2;
3815 info->data=NULL;
3816 info->count=0;
3818 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3819 sending a ffpcn() request first */
3821 if ( !option )
3822 return WERR_BADFID;
3824 get_printer_snum(p, hnd, &snum);
3826 for (i=0; i<option->count; i++) {
3827 option_type=&option->ctr.type[i];
3829 switch ( option_type->type ) {
3830 case PRINTER_NOTIFY_TYPE:
3831 if(construct_notify_printer_info(Printer, info, snum,
3832 option_type, id,
3833 mem_ctx))
3834 id--;
3835 break;
3837 case JOB_NOTIFY_TYPE: {
3838 NT_PRINTER_INFO_LEVEL *printer = NULL;
3840 count = print_queue_status(snum, &queue, &status);
3842 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3843 goto done;
3845 for (j=0; j<count; j++) {
3846 construct_notify_jobs_info(&queue[j], info,
3847 printer, snum,
3848 option_type,
3849 queue[j].job,
3850 mem_ctx);
3853 free_a_printer(&printer, 2);
3855 done:
3856 SAFE_FREE(queue);
3857 break;
3863 * Debugging information, don't delete.
3866 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3867 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3868 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3870 for (i=0; i<info->count; i++) {
3871 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3872 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3873 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3876 return WERR_OK;
3879 /********************************************************************
3880 * spoolss_rfnpcnex
3881 ********************************************************************/
3883 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3885 POLICY_HND *handle = &q_u->handle;
3886 SPOOL_NOTIFY_INFO *info = &r_u->info;
3888 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3889 WERROR result = WERR_BADFID;
3891 /* we always have a NOTIFY_INFO struct */
3892 r_u->info_ptr=0x1;
3894 if (!Printer) {
3895 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3896 OUR_HANDLE(handle)));
3897 goto done;
3900 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3903 * We are now using the change value, and
3904 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3905 * I don't have a global notification system, I'm sending back all the
3906 * informations even when _NOTHING_ has changed.
3909 /* We need to keep track of the change value to send back in
3910 RRPCN replies otherwise our updates are ignored. */
3912 Printer->notify.fnpcn = True;
3914 if (Printer->notify.client_connected) {
3915 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3916 Printer->notify.change = q_u->change;
3919 /* just ignore the SPOOL_NOTIFY_OPTION */
3921 switch (Printer->printer_type) {
3922 case PRINTER_HANDLE_IS_PRINTSERVER:
3923 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3924 break;
3926 case PRINTER_HANDLE_IS_PRINTER:
3927 result = printer_notify_info(p, handle, info, p->mem_ctx);
3928 break;
3931 Printer->notify.fnpcn = False;
3933 done:
3934 return result;
3937 /********************************************************************
3938 * construct_printer_info_0
3939 * fill a printer_info_0 struct
3940 ********************************************************************/
3942 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3944 pstring chaine;
3945 int count;
3946 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3947 counter_printer_0 *session_counter;
3948 uint32 global_counter;
3949 struct tm *t;
3950 time_t setuptime;
3951 print_status_struct status;
3953 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3954 return False;
3956 count = print_queue_length(snum, &status);
3958 /* check if we already have a counter for this printer */
3959 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3960 if (session_counter->snum == snum)
3961 break;
3964 /* it's the first time, add it to the list */
3965 if (session_counter==NULL) {
3966 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3967 free_a_printer(&ntprinter, 2);
3968 return False;
3970 ZERO_STRUCTP(session_counter);
3971 session_counter->snum=snum;
3972 session_counter->counter=0;
3973 DLIST_ADD(counter_list, session_counter);
3976 /* increment it */
3977 session_counter->counter++;
3979 /* JFM:
3980 * the global_counter should be stored in a TDB as it's common to all the clients
3981 * and should be zeroed on samba startup
3983 global_counter=session_counter->counter;
3985 pstrcpy(chaine,ntprinter->info_2->printername);
3987 init_unistr(&printer->printername, chaine);
3989 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3990 init_unistr(&printer->servername, chaine);
3992 printer->cjobs = count;
3993 printer->total_jobs = 0;
3994 printer->total_bytes = 0;
3996 setuptime = (time_t)ntprinter->info_2->setuptime;
3997 t=gmtime(&setuptime);
3999 printer->year = t->tm_year+1900;
4000 printer->month = t->tm_mon+1;
4001 printer->dayofweek = t->tm_wday;
4002 printer->day = t->tm_mday;
4003 printer->hour = t->tm_hour;
4004 printer->minute = t->tm_min;
4005 printer->second = t->tm_sec;
4006 printer->milliseconds = 0;
4008 printer->global_counter = global_counter;
4009 printer->total_pages = 0;
4011 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4012 printer->major_version = 0x0005; /* NT 5 */
4013 printer->build_version = 0x0893; /* build 2195 */
4015 printer->unknown7 = 0x1;
4016 printer->unknown8 = 0x0;
4017 printer->unknown9 = 0x0;
4018 printer->session_counter = session_counter->counter;
4019 printer->unknown11 = 0x0;
4020 printer->printer_errors = 0x0; /* number of print failure */
4021 printer->unknown13 = 0x0;
4022 printer->unknown14 = 0x1;
4023 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4024 printer->unknown16 = 0x0;
4025 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4026 printer->unknown18 = 0x0;
4027 printer->status = nt_printq_status(status.status);
4028 printer->unknown20 = 0x0;
4029 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4030 printer->unknown22 = 0x0;
4031 printer->unknown23 = 0x6; /* 6 ???*/
4032 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4033 printer->unknown25 = 0;
4034 printer->unknown26 = 0;
4035 printer->unknown27 = 0;
4036 printer->unknown28 = 0;
4037 printer->unknown29 = 0;
4039 free_a_printer(&ntprinter,2);
4040 return (True);
4043 /********************************************************************
4044 * construct_printer_info_1
4045 * fill a printer_info_1 struct
4046 ********************************************************************/
4047 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4049 pstring chaine;
4050 pstring chaine2;
4051 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4053 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4054 return False;
4056 printer->flags=flags;
4058 if (*ntprinter->info_2->comment == '\0') {
4059 init_unistr(&printer->comment, lp_comment(snum));
4060 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4061 ntprinter->info_2->drivername, lp_comment(snum));
4063 else {
4064 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4065 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4066 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4069 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4071 init_unistr(&printer->description, chaine);
4072 init_unistr(&printer->name, chaine2);
4074 free_a_printer(&ntprinter,2);
4076 return True;
4079 /****************************************************************************
4080 Free a DEVMODE struct.
4081 ****************************************************************************/
4083 static void free_dev_mode(DEVICEMODE *dev)
4085 if (dev == NULL)
4086 return;
4088 SAFE_FREE(dev->private);
4089 SAFE_FREE(dev);
4093 /****************************************************************************
4094 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4095 should be valid upon entry
4096 ****************************************************************************/
4098 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4100 if ( !devmode || !ntdevmode )
4101 return False;
4103 init_unistr(&devmode->devicename, ntdevmode->devicename);
4105 init_unistr(&devmode->formname, ntdevmode->formname);
4107 devmode->specversion = ntdevmode->specversion;
4108 devmode->driverversion = ntdevmode->driverversion;
4109 devmode->size = ntdevmode->size;
4110 devmode->driverextra = ntdevmode->driverextra;
4111 devmode->fields = ntdevmode->fields;
4113 devmode->orientation = ntdevmode->orientation;
4114 devmode->papersize = ntdevmode->papersize;
4115 devmode->paperlength = ntdevmode->paperlength;
4116 devmode->paperwidth = ntdevmode->paperwidth;
4117 devmode->scale = ntdevmode->scale;
4118 devmode->copies = ntdevmode->copies;
4119 devmode->defaultsource = ntdevmode->defaultsource;
4120 devmode->printquality = ntdevmode->printquality;
4121 devmode->color = ntdevmode->color;
4122 devmode->duplex = ntdevmode->duplex;
4123 devmode->yresolution = ntdevmode->yresolution;
4124 devmode->ttoption = ntdevmode->ttoption;
4125 devmode->collate = ntdevmode->collate;
4126 devmode->icmmethod = ntdevmode->icmmethod;
4127 devmode->icmintent = ntdevmode->icmintent;
4128 devmode->mediatype = ntdevmode->mediatype;
4129 devmode->dithertype = ntdevmode->dithertype;
4131 if (ntdevmode->private != NULL) {
4132 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4133 return False;
4136 return True;
4139 /****************************************************************************
4140 Create a DEVMODE struct. Returns malloced memory.
4141 ****************************************************************************/
4143 DEVICEMODE *construct_dev_mode(int snum)
4145 NT_PRINTER_INFO_LEVEL *printer = NULL;
4146 DEVICEMODE *devmode = NULL;
4148 DEBUG(7,("construct_dev_mode\n"));
4150 DEBUGADD(8,("getting printer characteristics\n"));
4152 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4153 return NULL;
4155 if ( !printer->info_2->devmode ) {
4156 DEBUG(5, ("BONG! There was no device mode!\n"));
4157 goto done;
4160 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4161 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4162 goto done;
4165 ZERO_STRUCTP(devmode);
4167 DEBUGADD(8,("loading DEVICEMODE\n"));
4169 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4170 free_dev_mode( devmode );
4171 devmode = NULL;
4174 done:
4175 free_a_printer(&printer,2);
4177 return devmode;
4180 /********************************************************************
4181 * construct_printer_info_2
4182 * fill a printer_info_2 struct
4183 ********************************************************************/
4185 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4187 int count;
4188 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4190 print_status_struct status;
4192 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4193 return False;
4195 count = print_queue_length(snum, &status);
4197 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4198 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4199 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4200 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4201 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4203 if (*ntprinter->info_2->comment == '\0')
4204 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4205 else
4206 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4208 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4209 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4210 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4211 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4212 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4214 printer->attributes = ntprinter->info_2->attributes;
4216 printer->priority = ntprinter->info_2->priority; /* priority */
4217 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4218 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4219 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4220 printer->status = nt_printq_status(status.status); /* status */
4221 printer->cjobs = count; /* jobs */
4222 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4224 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4225 DEBUG(8, ("Returning NULL Devicemode!\n"));
4228 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4229 /* steal the printer info sec_desc structure. [badly done]. */
4230 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4231 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4232 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4233 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4235 else {
4236 printer->secdesc = NULL;
4239 free_a_printer(&ntprinter, 2);
4240 return True;
4243 /********************************************************************
4244 * construct_printer_info_3
4245 * fill a printer_info_3 struct
4246 ********************************************************************/
4248 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4250 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4251 PRINTER_INFO_3 *printer = NULL;
4253 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4254 return False;
4256 *pp_printer = NULL;
4257 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4258 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4259 return False;
4262 ZERO_STRUCTP(printer);
4264 printer->flags = 4; /* These are the components of the SD we are returning. */
4265 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4266 /* steal the printer info sec_desc structure. [badly done]. */
4267 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4269 #if 0
4271 * Set the flags for the components we are returning.
4274 if (printer->secdesc->owner_sid)
4275 printer->flags |= OWNER_SECURITY_INFORMATION;
4277 if (printer->secdesc->grp_sid)
4278 printer->flags |= GROUP_SECURITY_INFORMATION;
4280 if (printer->secdesc->dacl)
4281 printer->flags |= DACL_SECURITY_INFORMATION;
4283 if (printer->secdesc->sacl)
4284 printer->flags |= SACL_SECURITY_INFORMATION;
4285 #endif
4287 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4288 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4289 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4292 free_a_printer(&ntprinter, 2);
4294 *pp_printer = printer;
4295 return True;
4298 /********************************************************************
4299 * construct_printer_info_4
4300 * fill a printer_info_4 struct
4301 ********************************************************************/
4303 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4305 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4307 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4308 return False;
4310 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4311 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4312 printer->attributes = ntprinter->info_2->attributes;
4314 free_a_printer(&ntprinter, 2);
4315 return True;
4318 /********************************************************************
4319 * construct_printer_info_5
4320 * fill a printer_info_5 struct
4321 ********************************************************************/
4323 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4325 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4327 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4328 return False;
4330 init_unistr(&printer->printername, ntprinter->info_2->printername);
4331 init_unistr(&printer->portname, ntprinter->info_2->portname);
4332 printer->attributes = ntprinter->info_2->attributes;
4334 /* these two are not used by NT+ according to MSDN */
4336 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4337 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4339 free_a_printer(&ntprinter, 2);
4341 return True;
4344 /********************************************************************
4345 * construct_printer_info_7
4346 * fill a printer_info_7 struct
4347 ********************************************************************/
4349 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4351 char *guid_str = NULL;
4352 struct uuid guid;
4354 if (is_printer_published(print_hnd, snum, &guid)) {
4355 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4356 strupper_m(guid_str);
4357 init_unistr(&printer->guid, guid_str);
4358 printer->action = SPOOL_DS_PUBLISH;
4359 } else {
4360 init_unistr(&printer->guid, "");
4361 printer->action = SPOOL_DS_UNPUBLISH;
4364 return True;
4367 /********************************************************************
4368 Spoolss_enumprinters.
4369 ********************************************************************/
4371 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4373 int snum;
4374 int i;
4375 int n_services=lp_numservices();
4376 PRINTER_INFO_1 *tp, *printers=NULL;
4377 PRINTER_INFO_1 current_prt;
4378 WERROR result = WERR_OK;
4380 DEBUG(4,("enum_all_printers_info_1\n"));
4382 for (snum=0; snum<n_services; snum++) {
4383 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4384 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4386 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4387 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4388 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4389 SAFE_FREE(printers);
4390 *returned=0;
4391 return WERR_NOMEM;
4393 else printers = tp;
4394 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4396 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4397 (*returned)++;
4402 /* check the required size. */
4403 for (i=0; i<*returned; i++)
4404 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4406 if (*needed > offered) {
4407 result = WERR_INSUFFICIENT_BUFFER;
4408 goto out;
4411 if (!rpcbuf_alloc_size(buffer, *needed)) {
4412 result = WERR_NOMEM;
4413 goto out;
4416 /* fill the buffer with the structures */
4417 for (i=0; i<*returned; i++)
4418 smb_io_printer_info_1("", buffer, &printers[i], 0);
4420 out:
4421 /* clear memory */
4423 SAFE_FREE(printers);
4425 if ( !W_ERROR_IS_OK(result) )
4426 *returned = 0;
4428 return result;
4431 /********************************************************************
4432 enum_all_printers_info_1_local.
4433 *********************************************************************/
4435 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4437 DEBUG(4,("enum_all_printers_info_1_local\n"));
4439 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4442 /********************************************************************
4443 enum_all_printers_info_1_name.
4444 *********************************************************************/
4446 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4448 char *s = name;
4450 DEBUG(4,("enum_all_printers_info_1_name\n"));
4452 if ((name[0] == '\\') && (name[1] == '\\'))
4453 s = name + 2;
4455 if (is_myname_or_ipaddr(s)) {
4456 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4458 else
4459 return WERR_INVALID_NAME;
4462 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4463 /********************************************************************
4464 enum_all_printers_info_1_remote.
4465 *********************************************************************/
4467 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4469 PRINTER_INFO_1 *printer;
4470 fstring printername;
4471 fstring desc;
4472 fstring comment;
4473 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4474 WERROR result = WERR_OK;
4476 /* JFM: currently it's more a place holder than anything else.
4477 * In the spooler world there is a notion of server registration.
4478 * the print servers are registered on the PDC (in the same domain)
4480 * We should have a TDB here. The registration is done thru an
4481 * undocumented RPC call.
4484 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4485 return WERR_NOMEM;
4487 *returned=1;
4489 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4490 slprintf(desc, sizeof(desc)-1,"%s", name);
4491 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4493 init_unistr(&printer->description, desc);
4494 init_unistr(&printer->name, printername);
4495 init_unistr(&printer->comment, comment);
4496 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4498 /* check the required size. */
4499 *needed += spoolss_size_printer_info_1(printer);
4501 if (*needed > offered) {
4502 result = WERR_INSUFFICIENT_BUFFER;
4503 goto out;
4506 if (!rpcbuf_alloc_size(buffer, *needed)) {
4507 result = WERR_NOMEM;
4508 goto out;
4511 /* fill the buffer with the structures */
4512 smb_io_printer_info_1("", buffer, printer, 0);
4514 out:
4515 /* clear memory */
4516 SAFE_FREE(printer);
4518 if ( !W_ERROR_IS_OK(result) )
4519 *returned = 0;
4521 return result;
4524 #endif
4526 /********************************************************************
4527 enum_all_printers_info_1_network.
4528 *********************************************************************/
4530 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4532 char *s = name;
4534 DEBUG(4,("enum_all_printers_info_1_network\n"));
4536 /* If we respond to a enum_printers level 1 on our name with flags
4537 set to PRINTER_ENUM_REMOTE with a list of printers then these
4538 printers incorrectly appear in the APW browse list.
4539 Specifically the printers for the server appear at the workgroup
4540 level where all the other servers in the domain are
4541 listed. Windows responds to this call with a
4542 WERR_CAN_NOT_COMPLETE so we should do the same. */
4544 if (name[0] == '\\' && name[1] == '\\')
4545 s = name + 2;
4547 if (is_myname_or_ipaddr(s))
4548 return WERR_CAN_NOT_COMPLETE;
4550 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4553 /********************************************************************
4554 * api_spoolss_enumprinters
4556 * called from api_spoolss_enumprinters (see this to understand)
4557 ********************************************************************/
4559 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4561 int snum;
4562 int i;
4563 int n_services=lp_numservices();
4564 PRINTER_INFO_2 *tp, *printers=NULL;
4565 PRINTER_INFO_2 current_prt;
4566 WERROR result = WERR_OK;
4568 for (snum=0; snum<n_services; snum++) {
4569 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4570 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4572 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4573 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4574 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4575 SAFE_FREE(printers);
4576 *returned = 0;
4577 return WERR_NOMEM;
4579 else printers = tp;
4580 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4581 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4582 (*returned)++;
4587 /* check the required size. */
4588 for (i=0; i<*returned; i++)
4589 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4591 if (*needed > offered) {
4592 result = WERR_INSUFFICIENT_BUFFER;
4593 goto out;
4596 if (!rpcbuf_alloc_size(buffer, *needed)) {
4597 result = WERR_NOMEM;
4598 goto out;
4601 /* fill the buffer with the structures */
4602 for (i=0; i<*returned; i++)
4603 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4605 out:
4606 /* clear memory */
4607 for (i=0; i<*returned; i++) {
4608 free_devmode(printers[i].devmode);
4610 SAFE_FREE(printers);
4612 if ( !W_ERROR_IS_OK(result) )
4613 *returned = 0;
4615 return result;
4618 /********************************************************************
4619 * handle enumeration of printers at level 1
4620 ********************************************************************/
4622 static WERROR enumprinters_level1( uint32 flags, fstring name,
4623 RPC_BUFFER *buffer, uint32 offered,
4624 uint32 *needed, uint32 *returned)
4626 /* Not all the flags are equals */
4628 if (flags & PRINTER_ENUM_LOCAL)
4629 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4631 if (flags & PRINTER_ENUM_NAME)
4632 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4634 #if 0 /* JERRY - disabled for now */
4635 if (flags & PRINTER_ENUM_REMOTE)
4636 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4637 #endif
4639 if (flags & PRINTER_ENUM_NETWORK)
4640 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4642 return WERR_OK; /* NT4sp5 does that */
4645 /********************************************************************
4646 * handle enumeration of printers at level 2
4647 ********************************************************************/
4649 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4650 RPC_BUFFER *buffer, uint32 offered,
4651 uint32 *needed, uint32 *returned)
4653 char *s = servername;
4655 if (flags & PRINTER_ENUM_LOCAL) {
4656 return enum_all_printers_info_2(buffer, offered, needed, returned);
4659 if (flags & PRINTER_ENUM_NAME) {
4660 if ((servername[0] == '\\') && (servername[1] == '\\'))
4661 s = servername + 2;
4662 if (is_myname_or_ipaddr(s))
4663 return enum_all_printers_info_2(buffer, offered, needed, returned);
4664 else
4665 return WERR_INVALID_NAME;
4668 if (flags & PRINTER_ENUM_REMOTE)
4669 return WERR_UNKNOWN_LEVEL;
4671 return WERR_OK;
4674 /********************************************************************
4675 * handle enumeration of printers at level 5
4676 ********************************************************************/
4678 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4679 RPC_BUFFER *buffer, uint32 offered,
4680 uint32 *needed, uint32 *returned)
4682 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4683 return WERR_OK;
4686 /********************************************************************
4687 * api_spoolss_enumprinters
4689 * called from api_spoolss_enumprinters (see this to understand)
4690 ********************************************************************/
4692 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4694 uint32 flags = q_u->flags;
4695 UNISTR2 *servername = &q_u->servername;
4696 uint32 level = q_u->level;
4697 RPC_BUFFER *buffer = NULL;
4698 uint32 offered = q_u->offered;
4699 uint32 *needed = &r_u->needed;
4700 uint32 *returned = &r_u->returned;
4702 fstring name;
4704 /* that's an [in out] buffer */
4706 if ( q_u->buffer ) {
4707 rpcbuf_move(q_u->buffer, &r_u->buffer);
4708 buffer = r_u->buffer;
4711 DEBUG(4,("_spoolss_enumprinters\n"));
4713 *needed=0;
4714 *returned=0;
4717 * Level 1:
4718 * flags==PRINTER_ENUM_NAME
4719 * if name=="" then enumerates all printers
4720 * if name!="" then enumerate the printer
4721 * flags==PRINTER_ENUM_REMOTE
4722 * name is NULL, enumerate printers
4723 * Level 2: name!="" enumerates printers, name can't be NULL
4724 * Level 3: doesn't exist
4725 * Level 4: does a local registry lookup
4726 * Level 5: same as Level 2
4729 unistr2_to_ascii(name, servername, sizeof(name)-1);
4730 strupper_m(name);
4732 switch (level) {
4733 case 1:
4734 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4735 case 2:
4736 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4737 case 5:
4738 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4739 case 3:
4740 case 4:
4741 break;
4743 return WERR_UNKNOWN_LEVEL;
4746 /****************************************************************************
4747 ****************************************************************************/
4749 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4751 PRINTER_INFO_0 *printer=NULL;
4752 WERROR result = WERR_OK;
4754 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4755 return WERR_NOMEM;
4757 construct_printer_info_0(print_hnd, printer, snum);
4759 /* check the required size. */
4760 *needed += spoolss_size_printer_info_0(printer);
4762 if (*needed > offered) {
4763 result = WERR_INSUFFICIENT_BUFFER;
4764 goto out;
4767 if (!rpcbuf_alloc_size(buffer, *needed)) {
4768 result = WERR_NOMEM;
4769 goto out;
4772 /* fill the buffer with the structures */
4773 smb_io_printer_info_0("", buffer, printer, 0);
4775 out:
4776 /* clear memory */
4778 SAFE_FREE(printer);
4780 return result;
4783 /****************************************************************************
4784 ****************************************************************************/
4786 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4788 PRINTER_INFO_1 *printer=NULL;
4789 WERROR result = WERR_OK;
4791 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4792 return WERR_NOMEM;
4794 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4796 /* check the required size. */
4797 *needed += spoolss_size_printer_info_1(printer);
4799 if (*needed > offered) {
4800 result = WERR_INSUFFICIENT_BUFFER;
4801 goto out;
4804 if (!rpcbuf_alloc_size(buffer, *needed)) {
4805 result = WERR_NOMEM;
4806 goto out;
4809 /* fill the buffer with the structures */
4810 smb_io_printer_info_1("", buffer, printer, 0);
4812 out:
4813 /* clear memory */
4814 SAFE_FREE(printer);
4816 return result;
4819 /****************************************************************************
4820 ****************************************************************************/
4822 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4824 PRINTER_INFO_2 *printer=NULL;
4825 WERROR result = WERR_OK;
4827 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4828 return WERR_NOMEM;
4830 construct_printer_info_2(print_hnd, printer, snum);
4832 /* check the required size. */
4833 *needed += spoolss_size_printer_info_2(printer);
4835 if (*needed > offered) {
4836 result = WERR_INSUFFICIENT_BUFFER;
4837 goto out;
4840 if (!rpcbuf_alloc_size(buffer, *needed)) {
4841 result = WERR_NOMEM;
4842 goto out;
4845 /* fill the buffer with the structures */
4846 if (!smb_io_printer_info_2("", buffer, printer, 0))
4847 result = WERR_NOMEM;
4849 out:
4850 /* clear memory */
4851 free_printer_info_2(printer);
4853 return result;
4856 /****************************************************************************
4857 ****************************************************************************/
4859 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4861 PRINTER_INFO_3 *printer=NULL;
4862 WERROR result = WERR_OK;
4864 if (!construct_printer_info_3(print_hnd, &printer, snum))
4865 return WERR_NOMEM;
4867 /* check the required size. */
4868 *needed += spoolss_size_printer_info_3(printer);
4870 if (*needed > offered) {
4871 result = WERR_INSUFFICIENT_BUFFER;
4872 goto out;
4875 if (!rpcbuf_alloc_size(buffer, *needed)) {
4876 result = WERR_NOMEM;
4877 goto out;
4880 /* fill the buffer with the structures */
4881 smb_io_printer_info_3("", buffer, printer, 0);
4883 out:
4884 /* clear memory */
4885 free_printer_info_3(printer);
4887 return result;
4890 /****************************************************************************
4891 ****************************************************************************/
4893 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4895 PRINTER_INFO_4 *printer=NULL;
4896 WERROR result = WERR_OK;
4898 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4899 return WERR_NOMEM;
4901 if (!construct_printer_info_4(print_hnd, printer, snum))
4902 return WERR_NOMEM;
4904 /* check the required size. */
4905 *needed += spoolss_size_printer_info_4(printer);
4907 if (*needed > offered) {
4908 result = WERR_INSUFFICIENT_BUFFER;
4909 goto out;
4912 if (!rpcbuf_alloc_size(buffer, *needed)) {
4913 result = WERR_NOMEM;
4914 goto out;
4917 /* fill the buffer with the structures */
4918 smb_io_printer_info_4("", buffer, printer, 0);
4920 out:
4921 /* clear memory */
4922 free_printer_info_4(printer);
4924 return result;
4927 /****************************************************************************
4928 ****************************************************************************/
4930 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4932 PRINTER_INFO_5 *printer=NULL;
4933 WERROR result = WERR_OK;
4935 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4936 return WERR_NOMEM;
4938 if (!construct_printer_info_5(print_hnd, printer, snum))
4939 return WERR_NOMEM;
4941 /* check the required size. */
4942 *needed += spoolss_size_printer_info_5(printer);
4944 if (*needed > offered) {
4945 result = WERR_INSUFFICIENT_BUFFER;
4946 goto out;
4949 if (!rpcbuf_alloc_size(buffer, *needed)) {
4950 result = WERR_NOMEM;
4951 goto out;
4954 /* fill the buffer with the structures */
4955 smb_io_printer_info_5("", buffer, printer, 0);
4957 out:
4958 /* clear memory */
4959 free_printer_info_5(printer);
4961 return result;
4964 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4966 PRINTER_INFO_7 *printer=NULL;
4967 WERROR result = WERR_OK;
4969 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4970 return WERR_NOMEM;
4972 if (!construct_printer_info_7(print_hnd, printer, snum))
4973 return WERR_NOMEM;
4975 /* check the required size. */
4976 *needed += spoolss_size_printer_info_7(printer);
4978 if (*needed > offered) {
4979 result = WERR_INSUFFICIENT_BUFFER;
4980 goto out;
4983 if (!rpcbuf_alloc_size(buffer, *needed)) {
4984 result = WERR_NOMEM;
4985 goto out;
4989 /* fill the buffer with the structures */
4990 smb_io_printer_info_7("", buffer, printer, 0);
4992 out:
4993 /* clear memory */
4994 free_printer_info_7(printer);
4996 return result;
4999 /****************************************************************************
5000 ****************************************************************************/
5002 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5004 POLICY_HND *handle = &q_u->handle;
5005 uint32 level = q_u->level;
5006 RPC_BUFFER *buffer = NULL;
5007 uint32 offered = q_u->offered;
5008 uint32 *needed = &r_u->needed;
5009 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5011 int snum;
5013 /* that's an [in out] buffer */
5015 if ( q_u->buffer ) {
5016 rpcbuf_move(q_u->buffer, &r_u->buffer);
5017 buffer = r_u->buffer;
5020 *needed=0;
5022 if (!get_printer_snum(p, handle, &snum))
5023 return WERR_BADFID;
5025 switch (level) {
5026 case 0:
5027 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5028 case 1:
5029 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5030 case 2:
5031 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5032 case 3:
5033 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5034 case 4:
5035 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5036 case 5:
5037 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5038 case 7:
5039 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5041 return WERR_UNKNOWN_LEVEL;
5044 /********************************************************************
5045 * fill a DRIVER_INFO_1 struct
5046 ********************************************************************/
5048 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5050 init_unistr( &info->name, driver.info_3->name);
5053 /********************************************************************
5054 * construct_printer_driver_info_1
5055 ********************************************************************/
5057 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5059 NT_PRINTER_INFO_LEVEL *printer = NULL;
5060 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5062 ZERO_STRUCT(driver);
5064 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5065 return WERR_INVALID_PRINTER_NAME;
5067 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5068 return WERR_UNKNOWN_PRINTER_DRIVER;
5070 fill_printer_driver_info_1(info, driver, servername, architecture);
5072 free_a_printer(&printer,2);
5074 return WERR_OK;
5077 /********************************************************************
5078 * construct_printer_driver_info_2
5079 * fill a printer_info_2 struct
5080 ********************************************************************/
5082 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5084 pstring temp;
5086 info->version=driver.info_3->cversion;
5088 init_unistr( &info->name, driver.info_3->name );
5089 init_unistr( &info->architecture, driver.info_3->environment );
5092 if (strlen(driver.info_3->driverpath)) {
5093 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5094 init_unistr( &info->driverpath, temp );
5095 } else
5096 init_unistr( &info->driverpath, "" );
5098 if (strlen(driver.info_3->datafile)) {
5099 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5100 init_unistr( &info->datafile, temp );
5101 } else
5102 init_unistr( &info->datafile, "" );
5104 if (strlen(driver.info_3->configfile)) {
5105 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5106 init_unistr( &info->configfile, temp );
5107 } else
5108 init_unistr( &info->configfile, "" );
5111 /********************************************************************
5112 * construct_printer_driver_info_2
5113 * fill a printer_info_2 struct
5114 ********************************************************************/
5116 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5118 NT_PRINTER_INFO_LEVEL *printer = NULL;
5119 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5121 ZERO_STRUCT(printer);
5122 ZERO_STRUCT(driver);
5124 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5125 return WERR_INVALID_PRINTER_NAME;
5127 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5128 return WERR_UNKNOWN_PRINTER_DRIVER;
5130 fill_printer_driver_info_2(info, driver, servername);
5132 free_a_printer(&printer,2);
5134 return WERR_OK;
5137 /********************************************************************
5138 * copy a strings array and convert to UNICODE
5140 * convert an array of ascii string to a UNICODE string
5141 ********************************************************************/
5143 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5145 int i=0;
5146 int j=0;
5147 const char *v;
5148 pstring line;
5149 uint16 *tuary;
5151 DEBUG(6,("init_unistr_array\n"));
5152 *uni_array=NULL;
5154 while (True)
5156 if ( !char_array )
5157 v = "";
5158 else
5160 v = char_array[i];
5161 if (!v)
5162 v = ""; /* hack to handle null lists */
5165 /* hack to allow this to be used in places other than when generating
5166 the list of dependent files */
5168 if ( servername )
5169 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5170 else
5171 pstrcpy( line, v );
5173 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5175 /* add one extra unit16 for the second terminating NULL */
5177 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5178 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5179 return 0;
5180 } else
5181 *uni_array = tuary;
5183 if ( !strlen(v) )
5184 break;
5186 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5187 i++;
5190 if (*uni_array) {
5191 /* special case for ""; we need to add both NULL's here */
5192 if (!j)
5193 (*uni_array)[j++]=0x0000;
5194 (*uni_array)[j]=0x0000;
5197 DEBUGADD(6,("last one:done\n"));
5199 /* return size of array in uint16's */
5201 return j+1;
5204 /********************************************************************
5205 * construct_printer_info_3
5206 * fill a printer_info_3 struct
5207 ********************************************************************/
5209 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5211 pstring temp;
5213 ZERO_STRUCTP(info);
5215 info->version=driver.info_3->cversion;
5217 init_unistr( &info->name, driver.info_3->name );
5218 init_unistr( &info->architecture, driver.info_3->environment );
5220 if (strlen(driver.info_3->driverpath)) {
5221 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5222 init_unistr( &info->driverpath, temp );
5223 } else
5224 init_unistr( &info->driverpath, "" );
5226 if (strlen(driver.info_3->datafile)) {
5227 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5228 init_unistr( &info->datafile, temp );
5229 } else
5230 init_unistr( &info->datafile, "" );
5232 if (strlen(driver.info_3->configfile)) {
5233 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5234 init_unistr( &info->configfile, temp );
5235 } else
5236 init_unistr( &info->configfile, "" );
5238 if (strlen(driver.info_3->helpfile)) {
5239 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5240 init_unistr( &info->helpfile, temp );
5241 } else
5242 init_unistr( &info->helpfile, "" );
5244 init_unistr( &info->monitorname, driver.info_3->monitorname );
5245 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5247 info->dependentfiles=NULL;
5248 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5251 /********************************************************************
5252 * construct_printer_info_3
5253 * fill a printer_info_3 struct
5254 ********************************************************************/
5256 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5258 NT_PRINTER_INFO_LEVEL *printer = NULL;
5259 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5260 WERROR status;
5261 ZERO_STRUCT(driver);
5263 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5264 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5265 if (!W_ERROR_IS_OK(status))
5266 return WERR_INVALID_PRINTER_NAME;
5268 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5269 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5271 #if 0 /* JERRY */
5274 * I put this code in during testing. Helpful when commenting out the
5275 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5276 * as win2k always queries the driver using an infor level of 6.
5277 * I've left it in (but ifdef'd out) because I'll probably
5278 * use it in experimentation again in the future. --jerry 22/01/2002
5281 if (!W_ERROR_IS_OK(status)) {
5283 * Is this a W2k client ?
5285 if (version == 3) {
5286 /* Yes - try again with a WinNT driver. */
5287 version = 2;
5288 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5289 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5291 #endif
5293 if (!W_ERROR_IS_OK(status)) {
5294 free_a_printer(&printer,2);
5295 return WERR_UNKNOWN_PRINTER_DRIVER;
5298 #if 0 /* JERRY */
5300 #endif
5303 fill_printer_driver_info_3(info, driver, servername);
5305 free_a_printer(&printer,2);
5307 return WERR_OK;
5310 /********************************************************************
5311 * construct_printer_info_6
5312 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5313 ********************************************************************/
5315 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5317 pstring temp;
5318 fstring nullstr;
5320 ZERO_STRUCTP(info);
5321 memset(&nullstr, '\0', sizeof(fstring));
5323 info->version=driver.info_3->cversion;
5325 init_unistr( &info->name, driver.info_3->name );
5326 init_unistr( &info->architecture, driver.info_3->environment );
5328 if (strlen(driver.info_3->driverpath)) {
5329 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5330 init_unistr( &info->driverpath, temp );
5331 } else
5332 init_unistr( &info->driverpath, "" );
5334 if (strlen(driver.info_3->datafile)) {
5335 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5336 init_unistr( &info->datafile, temp );
5337 } else
5338 init_unistr( &info->datafile, "" );
5340 if (strlen(driver.info_3->configfile)) {
5341 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5342 init_unistr( &info->configfile, temp );
5343 } else
5344 init_unistr( &info->configfile, "" );
5346 if (strlen(driver.info_3->helpfile)) {
5347 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5348 init_unistr( &info->helpfile, temp );
5349 } else
5350 init_unistr( &info->helpfile, "" );
5352 init_unistr( &info->monitorname, driver.info_3->monitorname );
5353 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5355 info->dependentfiles = NULL;
5356 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5358 info->previousdrivernames=NULL;
5359 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5361 info->driver_date.low=0;
5362 info->driver_date.high=0;
5364 info->padding=0;
5365 info->driver_version_low=0;
5366 info->driver_version_high=0;
5368 init_unistr( &info->mfgname, "");
5369 init_unistr( &info->oem_url, "");
5370 init_unistr( &info->hardware_id, "");
5371 init_unistr( &info->provider, "");
5374 /********************************************************************
5375 * construct_printer_info_6
5376 * fill a printer_info_6 struct
5377 ********************************************************************/
5379 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5380 fstring servername, fstring architecture, uint32 version)
5382 NT_PRINTER_INFO_LEVEL *printer = NULL;
5383 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5384 WERROR status;
5386 ZERO_STRUCT(driver);
5388 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5390 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5392 if (!W_ERROR_IS_OK(status))
5393 return WERR_INVALID_PRINTER_NAME;
5395 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5397 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5399 if (!W_ERROR_IS_OK(status))
5402 * Is this a W2k client ?
5405 if (version < 3) {
5406 free_a_printer(&printer,2);
5407 return WERR_UNKNOWN_PRINTER_DRIVER;
5410 /* Yes - try again with a WinNT driver. */
5411 version = 2;
5412 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5413 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5414 if (!W_ERROR_IS_OK(status)) {
5415 free_a_printer(&printer,2);
5416 return WERR_UNKNOWN_PRINTER_DRIVER;
5420 fill_printer_driver_info_6(info, driver, servername);
5422 free_a_printer(&printer,2);
5423 free_a_printer_driver(driver, 3);
5425 return WERR_OK;
5428 /****************************************************************************
5429 ****************************************************************************/
5431 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5433 SAFE_FREE(info->dependentfiles);
5436 /****************************************************************************
5437 ****************************************************************************/
5439 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5441 SAFE_FREE(info->dependentfiles);
5444 /****************************************************************************
5445 ****************************************************************************/
5447 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5449 DRIVER_INFO_1 *info=NULL;
5450 WERROR result;
5452 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5453 return WERR_NOMEM;
5455 result = construct_printer_driver_info_1(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_1(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_1("", buffer, info, 0);
5475 out:
5476 /* clear memory */
5477 SAFE_FREE(info);
5479 return result;
5482 /****************************************************************************
5483 ****************************************************************************/
5485 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5487 DRIVER_INFO_2 *info=NULL;
5488 WERROR result;
5490 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5491 return WERR_NOMEM;
5493 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5494 if (!W_ERROR_IS_OK(result))
5495 goto out;
5497 /* check the required size. */
5498 *needed += spoolss_size_printer_driver_info_2(info);
5500 if (*needed > offered) {
5501 result = WERR_INSUFFICIENT_BUFFER;
5502 goto out;
5505 if (!rpcbuf_alloc_size(buffer, *needed)) {
5506 result = WERR_NOMEM;
5507 goto out;
5510 /* fill the buffer with the structures */
5511 smb_io_printer_driver_info_2("", buffer, info, 0);
5513 out:
5514 /* clear memory */
5515 SAFE_FREE(info);
5517 return result;
5520 /****************************************************************************
5521 ****************************************************************************/
5523 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5525 DRIVER_INFO_3 info;
5526 WERROR result;
5528 ZERO_STRUCT(info);
5530 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5531 if (!W_ERROR_IS_OK(result))
5532 goto out;
5534 /* check the required size. */
5535 *needed += spoolss_size_printer_driver_info_3(&info);
5537 if (*needed > offered) {
5538 result = WERR_INSUFFICIENT_BUFFER;
5539 goto out;
5542 if (!rpcbuf_alloc_size(buffer, *needed)) {
5543 result = WERR_NOMEM;
5544 goto out;
5547 /* fill the buffer with the structures */
5548 smb_io_printer_driver_info_3("", buffer, &info, 0);
5550 out:
5551 free_printer_driver_info_3(&info);
5553 return result;
5556 /****************************************************************************
5557 ****************************************************************************/
5559 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5561 DRIVER_INFO_6 info;
5562 WERROR result;
5564 ZERO_STRUCT(info);
5566 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5567 if (!W_ERROR_IS_OK(result))
5568 goto out;
5570 /* check the required size. */
5571 *needed += spoolss_size_printer_driver_info_6(&info);
5573 if (*needed > offered) {
5574 result = WERR_INSUFFICIENT_BUFFER;
5575 goto out;
5578 if (!rpcbuf_alloc_size(buffer, *needed)) {
5579 result = WERR_NOMEM;
5580 goto out;
5583 /* fill the buffer with the structures */
5584 smb_io_printer_driver_info_6("", buffer, &info, 0);
5586 out:
5587 free_printer_driver_info_6(&info);
5589 return result;
5592 /****************************************************************************
5593 ****************************************************************************/
5595 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5597 POLICY_HND *handle = &q_u->handle;
5598 UNISTR2 *uni_arch = &q_u->architecture;
5599 uint32 level = q_u->level;
5600 uint32 clientmajorversion = q_u->clientmajorversion;
5601 RPC_BUFFER *buffer = NULL;
5602 uint32 offered = q_u->offered;
5603 uint32 *needed = &r_u->needed;
5604 uint32 *servermajorversion = &r_u->servermajorversion;
5605 uint32 *serverminorversion = &r_u->serverminorversion;
5606 Printer_entry *printer;
5608 fstring servername;
5609 fstring architecture;
5610 int snum;
5612 /* that's an [in out] buffer */
5614 if ( q_u->buffer ) {
5615 rpcbuf_move(q_u->buffer, &r_u->buffer);
5616 buffer = r_u->buffer;
5619 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5621 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5622 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5623 return WERR_INVALID_PRINTER_NAME;
5626 *needed = 0;
5627 *servermajorversion = 0;
5628 *serverminorversion = 0;
5630 fstrcpy(servername, get_server_name( printer ));
5631 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5633 if (!get_printer_snum(p, handle, &snum))
5634 return WERR_BADFID;
5636 switch (level) {
5637 case 1:
5638 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5639 case 2:
5640 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5641 case 3:
5642 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5643 case 6:
5644 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5645 #if 0 /* JERRY */
5646 case 101:
5647 /* apparently this call is the equivalent of
5648 EnumPrinterDataEx() for the DsDriver key */
5649 break;
5650 #endif
5653 return WERR_UNKNOWN_LEVEL;
5656 /****************************************************************************
5657 ****************************************************************************/
5659 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5661 POLICY_HND *handle = &q_u->handle;
5663 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5665 if (!Printer) {
5666 DEBUG(3,("Error in startpageprinter printer handle\n"));
5667 return WERR_BADFID;
5670 Printer->page_started=True;
5671 return WERR_OK;
5674 /****************************************************************************
5675 ****************************************************************************/
5677 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5679 POLICY_HND *handle = &q_u->handle;
5680 int snum;
5682 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5684 if (!Printer) {
5685 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5686 return WERR_BADFID;
5689 if (!get_printer_snum(p, handle, &snum))
5690 return WERR_BADFID;
5692 Printer->page_started=False;
5693 print_job_endpage(snum, Printer->jobid);
5695 return WERR_OK;
5698 /********************************************************************
5699 * api_spoolss_getprinter
5700 * called from the spoolss dispatcher
5702 ********************************************************************/
5704 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5706 POLICY_HND *handle = &q_u->handle;
5707 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5708 uint32 *jobid = &r_u->jobid;
5710 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5711 int snum;
5712 pstring jobname;
5713 fstring datatype;
5714 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5715 struct current_user user;
5717 if (!Printer) {
5718 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5719 return WERR_BADFID;
5722 get_current_user(&user, p);
5725 * a nice thing with NT is it doesn't listen to what you tell it.
5726 * when asked to send _only_ RAW datas, it tries to send datas
5727 * in EMF format.
5729 * So I add checks like in NT Server ...
5732 if (info_1->p_datatype != 0) {
5733 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5734 if (strcmp(datatype, "RAW") != 0) {
5735 (*jobid)=0;
5736 return WERR_INVALID_DATATYPE;
5740 /* get the share number of the printer */
5741 if (!get_printer_snum(p, handle, &snum)) {
5742 return WERR_BADFID;
5745 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5747 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5749 /* An error occured in print_job_start() so return an appropriate
5750 NT error code. */
5752 if (Printer->jobid == -1) {
5753 return map_werror_from_unix(errno);
5756 Printer->document_started=True;
5757 (*jobid) = Printer->jobid;
5759 return WERR_OK;
5762 /********************************************************************
5763 * api_spoolss_getprinter
5764 * called from the spoolss dispatcher
5766 ********************************************************************/
5768 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5770 POLICY_HND *handle = &q_u->handle;
5772 return _spoolss_enddocprinter_internal(p, handle);
5775 /****************************************************************************
5776 ****************************************************************************/
5778 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5780 POLICY_HND *handle = &q_u->handle;
5781 uint32 buffer_size = q_u->buffer_size;
5782 uint8 *buffer = q_u->buffer;
5783 uint32 *buffer_written = &q_u->buffer_size2;
5784 int snum;
5785 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5787 if (!Printer) {
5788 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5789 r_u->buffer_written = q_u->buffer_size2;
5790 return WERR_BADFID;
5793 if (!get_printer_snum(p, handle, &snum))
5794 return WERR_BADFID;
5796 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5797 if (*buffer_written == -1) {
5798 r_u->buffer_written = 0;
5799 if (errno == ENOSPC)
5800 return WERR_NO_SPOOL_SPACE;
5801 else
5802 return WERR_ACCESS_DENIED;
5805 r_u->buffer_written = q_u->buffer_size2;
5807 return WERR_OK;
5810 /********************************************************************
5811 * api_spoolss_getprinter
5812 * called from the spoolss dispatcher
5814 ********************************************************************/
5816 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5817 pipes_struct *p)
5819 struct current_user user;
5820 int snum;
5821 WERROR errcode = WERR_BADFUNC;
5822 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5824 get_current_user(&user, p);
5826 if (!Printer) {
5827 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5828 return WERR_BADFID;
5831 if (!get_printer_snum(p, handle, &snum))
5832 return WERR_BADFID;
5834 switch (command) {
5835 case PRINTER_CONTROL_PAUSE:
5836 if (print_queue_pause(&user, snum, &errcode)) {
5837 errcode = WERR_OK;
5839 break;
5840 case PRINTER_CONTROL_RESUME:
5841 case PRINTER_CONTROL_UNPAUSE:
5842 if (print_queue_resume(&user, snum, &errcode)) {
5843 errcode = WERR_OK;
5845 break;
5846 case PRINTER_CONTROL_PURGE:
5847 if (print_queue_purge(&user, snum, &errcode)) {
5848 errcode = WERR_OK;
5850 break;
5851 default:
5852 return WERR_UNKNOWN_LEVEL;
5855 return errcode;
5858 /********************************************************************
5859 * api_spoolss_abortprinter
5860 * From MSDN: "Deletes printer's spool file if printer is configured
5861 * for spooling"
5862 ********************************************************************/
5864 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5866 POLICY_HND *handle = &q_u->handle;
5867 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5868 int snum;
5869 struct current_user user;
5870 WERROR errcode = WERR_OK;
5872 if (!Printer) {
5873 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5874 return WERR_BADFID;
5877 if (!get_printer_snum(p, handle, &snum))
5878 return WERR_BADFID;
5880 get_current_user( &user, p );
5882 print_job_delete( &user, snum, Printer->jobid, &errcode );
5884 return errcode;
5887 /********************************************************************
5888 * called by spoolss_api_setprinter
5889 * when updating a printer description
5890 ********************************************************************/
5892 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5893 const SPOOL_PRINTER_INFO_LEVEL *info,
5894 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5896 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5897 WERROR result;
5898 int snum;
5900 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5902 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5903 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5904 OUR_HANDLE(handle)));
5906 result = WERR_BADFID;
5907 goto done;
5910 /* Check the user has permissions to change the security
5911 descriptor. By experimentation with two NT machines, the user
5912 requires Full Access to the printer to change security
5913 information. */
5915 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5916 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5917 result = WERR_ACCESS_DENIED;
5918 goto done;
5921 /* NT seems to like setting the security descriptor even though
5922 nothing may have actually changed. */
5924 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5926 if (DEBUGLEVEL >= 10) {
5927 SEC_ACL *the_acl;
5928 int i;
5930 the_acl = old_secdesc_ctr->sec->dacl;
5931 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5932 PRINTERNAME(snum), the_acl->num_aces));
5934 for (i = 0; i < the_acl->num_aces; i++) {
5935 fstring sid_str;
5937 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5939 DEBUG(10, ("%s 0x%08x\n", sid_str,
5940 the_acl->ace[i].info.mask));
5943 the_acl = secdesc_ctr->sec->dacl;
5945 if (the_acl) {
5946 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5947 PRINTERNAME(snum), the_acl->num_aces));
5949 for (i = 0; i < the_acl->num_aces; i++) {
5950 fstring sid_str;
5952 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5954 DEBUG(10, ("%s 0x%08x\n", sid_str,
5955 the_acl->ace[i].info.mask));
5957 } else {
5958 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5962 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5964 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5965 result = WERR_OK;
5966 goto done;
5969 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5971 done:
5973 return result;
5976 /********************************************************************
5977 Canonicalize printer info from a client
5979 ATTN: It does not matter what we set the servername to hear
5980 since we do the necessary work in get_a_printer() to set it to
5981 the correct value based on what the client sent in the
5982 _spoolss_open_printer_ex().
5983 ********************************************************************/
5985 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5987 fstring printername;
5988 const char *p;
5990 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5991 "portname=%s drivername=%s comment=%s location=%s\n",
5992 info->servername, info->printername, info->sharename,
5993 info->portname, info->drivername, info->comment, info->location));
5995 /* we force some elements to "correct" values */
5996 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5997 fstrcpy(info->sharename, lp_servicename(snum));
5999 /* check to see if we allow printername != sharename */
6001 if ( lp_force_printername(snum) ) {
6002 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6003 global_myname(), info->sharename );
6004 } else {
6006 /* make sure printername is in \\server\printername format */
6008 fstrcpy( printername, info->printername );
6009 p = printername;
6010 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6011 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6012 p++;
6015 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6016 global_myname(), p );
6019 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6020 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6024 return True;
6027 /****************************************************************************
6028 ****************************************************************************/
6030 static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6032 char *cmd = lp_addprinter_cmd();
6033 char **qlines;
6034 pstring command;
6035 int numlines;
6036 int ret;
6037 int fd;
6038 fstring remote_machine = "%m";
6039 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6040 BOOL is_print_op;
6042 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6044 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6045 cmd, printer->info_2->printername, printer->info_2->sharename,
6046 printer->info_2->portname, printer->info_2->drivername,
6047 printer->info_2->location, printer->info_2->comment, remote_machine);
6049 is_print_op = user_has_privileges( token, &se_printop );
6051 DEBUG(10,("Running [%s]\n", command));
6053 /********* BEGIN SePrintOperatorPrivilege **********/
6055 if ( is_print_op )
6056 become_root();
6058 if ( (ret = smbrun(command, &fd)) == 0 ) {
6059 /* Tell everyone we updated smb.conf. */
6060 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6063 if ( is_print_op )
6064 unbecome_root();
6066 /********* END SePrintOperatorPrivilege **********/
6068 DEBUGADD(10,("returned [%d]\n", ret));
6070 if ( ret != 0 ) {
6071 if (fd != -1)
6072 close(fd);
6073 return False;
6076 /* reload our services immediately */
6077 reload_services( False );
6079 numlines = 0;
6080 /* Get lines and convert them back to dos-codepage */
6081 qlines = fd_lines_load(fd, &numlines);
6082 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6083 close(fd);
6085 /* Set the portname to what the script says the portname should be. */
6086 /* but don't require anything to be return from the script exit a good error code */
6088 if (numlines) {
6089 /* Set the portname to what the script says the portname should be. */
6090 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6091 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6094 file_lines_free(qlines);
6095 return True;
6098 /********************************************************************
6099 * Called by spoolss_api_setprinter
6100 * when updating a printer description.
6101 ********************************************************************/
6103 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6104 const SPOOL_PRINTER_INFO_LEVEL *info,
6105 DEVICEMODE *devmode)
6107 int snum;
6108 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6109 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6110 WERROR result;
6111 UNISTR2 buffer;
6112 fstring asc_buffer;
6114 DEBUG(8,("update_printer\n"));
6116 result = WERR_OK;
6118 if (!Printer) {
6119 result = WERR_BADFID;
6120 goto done;
6123 if (!get_printer_snum(p, handle, &snum)) {
6124 result = WERR_BADFID;
6125 goto done;
6128 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6129 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6130 result = WERR_BADFID;
6131 goto done;
6134 DEBUGADD(8,("Converting info_2 struct\n"));
6137 * convert_printer_info converts the incoming
6138 * info from the client and overwrites the info
6139 * just read from the tdb in the pointer 'printer'.
6142 if (!convert_printer_info(info, printer, level)) {
6143 result = WERR_NOMEM;
6144 goto done;
6147 if (devmode) {
6148 /* we have a valid devmode
6149 convert it and link it*/
6151 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6152 if (!convert_devicemode(printer->info_2->printername, devmode,
6153 &printer->info_2->devmode)) {
6154 result = WERR_NOMEM;
6155 goto done;
6159 /* Do sanity check on the requested changes for Samba */
6161 if (!check_printer_ok(printer->info_2, snum)) {
6162 result = WERR_INVALID_PARAM;
6163 goto done;
6166 /* FIXME!!! If the driver has changed we really should verify that
6167 it is installed before doing much else --jerry */
6169 /* Check calling user has permission to update printer description */
6171 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6172 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6173 result = WERR_ACCESS_DENIED;
6174 goto done;
6177 /* Call addprinter hook */
6178 /* Check changes to see if this is really needed */
6180 if ( *lp_addprinter_cmd()
6181 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6182 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6183 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6184 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6186 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6187 result = WERR_ACCESS_DENIED;
6188 goto done;
6192 * make sure we actually reload the services after
6193 * this as smb.conf could have a new section in it
6194 * .... shouldn't .... but could
6196 reload_services(False);
6200 * When a *new* driver is bound to a printer, the drivername is used to
6201 * lookup previously saved driver initialization info, which is then
6202 * bound to the printer, simulating what happens in the Windows arch.
6204 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6206 if (!set_driver_init(printer, 2))
6208 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6209 printer->info_2->drivername));
6212 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6213 printer->info_2->drivername));
6215 notify_printer_driver(snum, printer->info_2->drivername);
6219 * flag which changes actually occured. This is a small subset of
6220 * all the possible changes. We also have to update things in the
6221 * DsSpooler key.
6224 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6225 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6226 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6227 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6229 notify_printer_comment(snum, printer->info_2->comment);
6232 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6233 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6234 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6235 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6237 notify_printer_sharename(snum, printer->info_2->sharename);
6240 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6241 char *pname;
6243 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6244 pname++;
6245 else
6246 pname = printer->info_2->printername;
6249 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6250 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6251 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6253 notify_printer_printername( snum, pname );
6256 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6257 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6258 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6259 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6261 notify_printer_port(snum, printer->info_2->portname);
6264 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6265 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6266 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6267 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6269 notify_printer_location(snum, printer->info_2->location);
6272 /* here we need to update some more DsSpooler keys */
6273 /* uNCName, serverName, shortServerName */
6275 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6276 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6277 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6278 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6279 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6281 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6282 global_myname(), printer->info_2->sharename );
6283 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6284 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6285 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6287 /* Update printer info */
6288 result = mod_a_printer(printer, 2);
6290 done:
6291 free_a_printer(&printer, 2);
6292 free_a_printer(&old_printer, 2);
6295 return result;
6298 /****************************************************************************
6299 ****************************************************************************/
6300 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6301 const SPOOL_PRINTER_INFO_LEVEL *info)
6303 #ifdef HAVE_ADS
6304 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6305 int snum;
6306 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6308 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6310 if (!Printer)
6311 return WERR_BADFID;
6313 if (!get_printer_snum(p, handle, &snum))
6314 return WERR_BADFID;
6316 nt_printer_publish(Printer, snum, info7->action);
6318 return WERR_OK;
6319 #else
6320 return WERR_UNKNOWN_LEVEL;
6321 #endif
6323 /****************************************************************************
6324 ****************************************************************************/
6326 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6328 POLICY_HND *handle = &q_u->handle;
6329 uint32 level = q_u->level;
6330 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6331 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6332 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6333 uint32 command = q_u->command;
6334 WERROR result;
6336 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6338 if (!Printer) {
6339 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6340 return WERR_BADFID;
6343 /* check the level */
6344 switch (level) {
6345 case 0:
6346 return control_printer(handle, command, p);
6347 case 2:
6348 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6349 if (!W_ERROR_IS_OK(result))
6350 return result;
6351 if (secdesc_ctr)
6352 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6353 return result;
6354 case 3:
6355 return update_printer_sec(handle, level, info, p,
6356 secdesc_ctr);
6357 case 7:
6358 return publish_or_unpublish_printer(p, handle, info);
6359 default:
6360 return WERR_UNKNOWN_LEVEL;
6364 /****************************************************************************
6365 ****************************************************************************/
6367 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6369 POLICY_HND *handle = &q_u->handle;
6370 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6372 if (!Printer) {
6373 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6374 return WERR_BADFID;
6377 if (Printer->notify.client_connected==True) {
6378 int snum = -1;
6380 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6381 snum = -1;
6382 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6383 !get_printer_snum(p, handle, &snum) )
6384 return WERR_BADFID;
6386 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6389 Printer->notify.flags=0;
6390 Printer->notify.options=0;
6391 Printer->notify.localmachine[0]='\0';
6392 Printer->notify.printerlocal=0;
6393 if (Printer->notify.option)
6394 free_spool_notify_option(&Printer->notify.option);
6395 Printer->notify.client_connected=False;
6397 return WERR_OK;
6400 /****************************************************************************
6401 ****************************************************************************/
6403 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6405 /* that's an [in out] buffer */
6407 if ( q_u->buffer )
6408 rpcbuf_move(q_u->buffer, &r_u->buffer);
6410 r_u->needed = 0;
6411 return WERR_INVALID_PARAM; /* this is what a NT server
6412 returns for AddJob. AddJob
6413 must fail on non-local
6414 printers */
6417 /****************************************************************************
6418 ****************************************************************************/
6420 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6421 int position, int snum,
6422 NT_PRINTER_INFO_LEVEL *ntprinter)
6424 struct tm *t;
6426 t=gmtime(&queue->time);
6428 job_info->jobid=queue->job;
6429 init_unistr(&job_info->printername, lp_servicename(snum));
6430 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6431 init_unistr(&job_info->username, queue->fs_user);
6432 init_unistr(&job_info->document, queue->fs_file);
6433 init_unistr(&job_info->datatype, "RAW");
6434 init_unistr(&job_info->text_status, "");
6435 job_info->status=nt_printj_status(queue->status);
6436 job_info->priority=queue->priority;
6437 job_info->position=position;
6438 job_info->totalpages=queue->page_count;
6439 job_info->pagesprinted=0;
6441 make_systemtime(&job_info->submitted, t);
6444 /****************************************************************************
6445 ****************************************************************************/
6447 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6448 int position, int snum,
6449 NT_PRINTER_INFO_LEVEL *ntprinter,
6450 DEVICEMODE *devmode)
6452 struct tm *t;
6454 t=gmtime(&queue->time);
6456 job_info->jobid=queue->job;
6458 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6460 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6461 init_unistr(&job_info->username, queue->fs_user);
6462 init_unistr(&job_info->document, queue->fs_file);
6463 init_unistr(&job_info->notifyname, queue->fs_user);
6464 init_unistr(&job_info->datatype, "RAW");
6465 init_unistr(&job_info->printprocessor, "winprint");
6466 init_unistr(&job_info->parameters, "");
6467 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6468 init_unistr(&job_info->text_status, "");
6470 /* and here the security descriptor */
6472 job_info->status=nt_printj_status(queue->status);
6473 job_info->priority=queue->priority;
6474 job_info->position=position;
6475 job_info->starttime=0;
6476 job_info->untiltime=0;
6477 job_info->totalpages=queue->page_count;
6478 job_info->size=queue->size;
6479 make_systemtime(&(job_info->submitted), t);
6480 job_info->timeelapsed=0;
6481 job_info->pagesprinted=0;
6483 job_info->devmode = devmode;
6485 return (True);
6488 /****************************************************************************
6489 Enumjobs at level 1.
6490 ****************************************************************************/
6492 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6493 NT_PRINTER_INFO_LEVEL *ntprinter,
6494 RPC_BUFFER *buffer, uint32 offered,
6495 uint32 *needed, uint32 *returned)
6497 JOB_INFO_1 *info;
6498 int i;
6499 WERROR result = WERR_OK;
6501 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6502 if (info==NULL) {
6503 SAFE_FREE(queue);
6504 *returned=0;
6505 return WERR_NOMEM;
6508 for (i=0; i<*returned; i++)
6509 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6511 SAFE_FREE(queue);
6513 /* check the required size. */
6514 for (i=0; i<*returned; i++)
6515 (*needed) += spoolss_size_job_info_1(&info[i]);
6517 if (*needed > offered) {
6518 result = WERR_INSUFFICIENT_BUFFER;
6519 goto out;
6522 if (!rpcbuf_alloc_size(buffer, *needed)) {
6523 result = WERR_NOMEM;
6524 goto out;
6527 /* fill the buffer with the structures */
6528 for (i=0; i<*returned; i++)
6529 smb_io_job_info_1("", buffer, &info[i], 0);
6531 out:
6532 /* clear memory */
6533 SAFE_FREE(info);
6535 if ( !W_ERROR_IS_OK(result) )
6536 *returned = 0;
6538 return result;
6541 /****************************************************************************
6542 Enumjobs at level 2.
6543 ****************************************************************************/
6545 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6546 NT_PRINTER_INFO_LEVEL *ntprinter,
6547 RPC_BUFFER *buffer, uint32 offered,
6548 uint32 *needed, uint32 *returned)
6550 JOB_INFO_2 *info = NULL;
6551 int i;
6552 WERROR result = WERR_OK;
6553 DEVICEMODE *devmode = NULL;
6555 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6556 *returned=0;
6557 return WERR_NOMEM;
6560 /* this should not be a failure condition if the devmode is NULL */
6562 devmode = construct_dev_mode(snum);
6564 for (i=0; i<*returned; i++)
6565 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6567 free_a_printer(&ntprinter, 2);
6568 SAFE_FREE(queue);
6570 /* check the required size. */
6571 for (i=0; i<*returned; i++)
6572 (*needed) += spoolss_size_job_info_2(&info[i]);
6574 if (*needed > offered) {
6575 result = WERR_INSUFFICIENT_BUFFER;
6576 goto out;
6579 if (!rpcbuf_alloc_size(buffer, *needed)) {
6580 result = WERR_NOMEM;
6581 goto out;
6584 /* fill the buffer with the structures */
6585 for (i=0; i<*returned; i++)
6586 smb_io_job_info_2("", buffer, &info[i], 0);
6588 out:
6589 free_devmode(devmode);
6590 SAFE_FREE(info);
6592 if ( !W_ERROR_IS_OK(result) )
6593 *returned = 0;
6595 return result;
6599 /****************************************************************************
6600 Enumjobs.
6601 ****************************************************************************/
6603 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6605 POLICY_HND *handle = &q_u->handle;
6606 uint32 level = q_u->level;
6607 RPC_BUFFER *buffer = NULL;
6608 uint32 offered = q_u->offered;
6609 uint32 *needed = &r_u->needed;
6610 uint32 *returned = &r_u->returned;
6611 WERROR wret;
6612 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6613 int snum;
6614 print_status_struct prt_status;
6615 print_queue_struct *queue=NULL;
6617 /* that's an [in out] buffer */
6619 if ( q_u->buffer ) {
6620 rpcbuf_move(q_u->buffer, &r_u->buffer);
6621 buffer = r_u->buffer;
6624 DEBUG(4,("_spoolss_enumjobs\n"));
6626 *needed=0;
6627 *returned=0;
6629 /* lookup the printer snum and tdb entry */
6631 if (!get_printer_snum(p, handle, &snum))
6632 return WERR_BADFID;
6634 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6635 if ( !W_ERROR_IS_OK(wret) )
6636 return wret;
6638 *returned = print_queue_status(snum, &queue, &prt_status);
6639 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6641 if (*returned == 0) {
6642 SAFE_FREE(queue);
6643 return WERR_OK;
6646 switch (level) {
6647 case 1:
6648 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6649 return wret;
6650 case 2:
6651 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6652 return wret;
6653 default:
6654 SAFE_FREE(queue);
6655 *returned=0;
6656 wret = WERR_UNKNOWN_LEVEL;
6659 free_a_printer( &ntprinter, 2 );
6660 return wret;
6663 /****************************************************************************
6664 ****************************************************************************/
6666 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6668 return WERR_OK;
6671 /****************************************************************************
6672 ****************************************************************************/
6674 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6676 POLICY_HND *handle = &q_u->handle;
6677 uint32 jobid = q_u->jobid;
6678 uint32 command = q_u->command;
6680 struct current_user user;
6681 int snum;
6682 WERROR errcode = WERR_BADFUNC;
6684 if (!get_printer_snum(p, handle, &snum)) {
6685 return WERR_BADFID;
6688 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6689 return WERR_INVALID_PRINTER_NAME;
6692 get_current_user(&user, p);
6694 switch (command) {
6695 case JOB_CONTROL_CANCEL:
6696 case JOB_CONTROL_DELETE:
6697 if (print_job_delete(&user, snum, jobid, &errcode)) {
6698 errcode = WERR_OK;
6700 break;
6701 case JOB_CONTROL_PAUSE:
6702 if (print_job_pause(&user, snum, jobid, &errcode)) {
6703 errcode = WERR_OK;
6705 break;
6706 case JOB_CONTROL_RESTART:
6707 case JOB_CONTROL_RESUME:
6708 if (print_job_resume(&user, snum, jobid, &errcode)) {
6709 errcode = WERR_OK;
6711 break;
6712 default:
6713 return WERR_UNKNOWN_LEVEL;
6716 return errcode;
6719 /****************************************************************************
6720 Enumerates all printer drivers at level 1.
6721 ****************************************************************************/
6723 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6725 int i;
6726 int ndrivers;
6727 uint32 version;
6728 fstring *list = NULL;
6729 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6730 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6731 WERROR result = WERR_OK;
6733 *returned=0;
6735 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6736 list=NULL;
6737 ndrivers=get_ntdrivers(&list, architecture, version);
6738 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6740 if(ndrivers == -1)
6741 return WERR_NOMEM;
6743 if(ndrivers != 0) {
6744 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6745 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6746 SAFE_FREE(driver_info_1);
6747 SAFE_FREE(list);
6748 return WERR_NOMEM;
6750 else driver_info_1 = tdi1;
6753 for (i=0; i<ndrivers; i++) {
6754 WERROR status;
6755 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6756 ZERO_STRUCT(driver);
6757 status = get_a_printer_driver(&driver, 3, list[i],
6758 architecture, version);
6759 if (!W_ERROR_IS_OK(status)) {
6760 SAFE_FREE(list);
6761 return status;
6763 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6764 free_a_printer_driver(driver, 3);
6767 *returned+=ndrivers;
6768 SAFE_FREE(list);
6771 /* check the required size. */
6772 for (i=0; i<*returned; i++) {
6773 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6774 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6777 if (*needed > offered) {
6778 result = WERR_INSUFFICIENT_BUFFER;
6779 goto out;
6782 if (!rpcbuf_alloc_size(buffer, *needed)) {
6783 result = WERR_NOMEM;
6784 goto out;
6787 /* fill the buffer with the driver structures */
6788 for (i=0; i<*returned; i++) {
6789 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6790 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6793 out:
6794 SAFE_FREE(driver_info_1);
6796 if ( !W_ERROR_IS_OK(result) )
6797 *returned = 0;
6799 return result;
6802 /****************************************************************************
6803 Enumerates all printer drivers at level 2.
6804 ****************************************************************************/
6806 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6808 int i;
6809 int ndrivers;
6810 uint32 version;
6811 fstring *list = NULL;
6812 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6813 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6814 WERROR result = WERR_OK;
6816 *returned=0;
6818 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6819 list=NULL;
6820 ndrivers=get_ntdrivers(&list, architecture, version);
6821 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6823 if(ndrivers == -1)
6824 return WERR_NOMEM;
6826 if(ndrivers != 0) {
6827 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6828 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6829 SAFE_FREE(driver_info_2);
6830 SAFE_FREE(list);
6831 return WERR_NOMEM;
6833 else driver_info_2 = tdi2;
6836 for (i=0; i<ndrivers; i++) {
6837 WERROR status;
6839 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6840 ZERO_STRUCT(driver);
6841 status = get_a_printer_driver(&driver, 3, list[i],
6842 architecture, version);
6843 if (!W_ERROR_IS_OK(status)) {
6844 SAFE_FREE(list);
6845 return status;
6847 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6848 free_a_printer_driver(driver, 3);
6851 *returned+=ndrivers;
6852 SAFE_FREE(list);
6855 /* check the required size. */
6856 for (i=0; i<*returned; i++) {
6857 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6858 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6861 if (*needed > offered) {
6862 result = WERR_INSUFFICIENT_BUFFER;
6863 goto out;
6866 if (!rpcbuf_alloc_size(buffer, *needed)) {
6867 result = WERR_NOMEM;
6868 goto out;
6871 /* fill the buffer with the form structures */
6872 for (i=0; i<*returned; i++) {
6873 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6874 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6877 out:
6878 SAFE_FREE(driver_info_2);
6880 if ( !W_ERROR_IS_OK(result) )
6881 *returned = 0;
6883 return result;
6886 /****************************************************************************
6887 Enumerates all printer drivers at level 3.
6888 ****************************************************************************/
6890 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6892 int i;
6893 int ndrivers;
6894 uint32 version;
6895 fstring *list = NULL;
6896 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6897 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6898 WERROR result = WERR_OK;
6900 *returned=0;
6902 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6903 list=NULL;
6904 ndrivers=get_ntdrivers(&list, architecture, version);
6905 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6907 if(ndrivers == -1)
6908 return WERR_NOMEM;
6910 if(ndrivers != 0) {
6911 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6912 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6913 SAFE_FREE(driver_info_3);
6914 SAFE_FREE(list);
6915 return WERR_NOMEM;
6917 else driver_info_3 = tdi3;
6920 for (i=0; i<ndrivers; i++) {
6921 WERROR status;
6923 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6924 ZERO_STRUCT(driver);
6925 status = get_a_printer_driver(&driver, 3, list[i],
6926 architecture, version);
6927 if (!W_ERROR_IS_OK(status)) {
6928 SAFE_FREE(list);
6929 return status;
6931 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6932 free_a_printer_driver(driver, 3);
6935 *returned+=ndrivers;
6936 SAFE_FREE(list);
6939 /* check the required size. */
6940 for (i=0; i<*returned; i++) {
6941 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6942 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6945 if (*needed > offered) {
6946 result = WERR_INSUFFICIENT_BUFFER;
6947 goto out;
6950 if (!rpcbuf_alloc_size(buffer, *needed)) {
6951 result = WERR_NOMEM;
6952 goto out;
6955 /* fill the buffer with the driver structures */
6956 for (i=0; i<*returned; i++) {
6957 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6958 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6961 out:
6962 for (i=0; i<*returned; i++)
6963 SAFE_FREE(driver_info_3[i].dependentfiles);
6965 SAFE_FREE(driver_info_3);
6967 if ( !W_ERROR_IS_OK(result) )
6968 *returned = 0;
6970 return result;
6973 /****************************************************************************
6974 Enumerates all printer drivers.
6975 ****************************************************************************/
6977 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6979 uint32 level = q_u->level;
6980 RPC_BUFFER *buffer = NULL;
6981 uint32 offered = q_u->offered;
6982 uint32 *needed = &r_u->needed;
6983 uint32 *returned = &r_u->returned;
6985 fstring servername;
6986 fstring architecture;
6988 /* that's an [in out] buffer */
6990 if ( q_u->buffer ) {
6991 rpcbuf_move(q_u->buffer, &r_u->buffer);
6992 buffer = r_u->buffer;
6995 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6997 *needed = 0;
6998 *returned = 0;
7000 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7001 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7003 if ( !is_myname_or_ipaddr( servername ) )
7004 return WERR_UNKNOWN_PRINTER_DRIVER;
7006 switch (level) {
7007 case 1:
7008 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7009 case 2:
7010 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7011 case 3:
7012 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7013 default:
7014 return WERR_UNKNOWN_LEVEL;
7018 /****************************************************************************
7019 ****************************************************************************/
7021 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7023 form->flag=list->flag;
7024 init_unistr(&form->name, list->name);
7025 form->width=list->width;
7026 form->length=list->length;
7027 form->left=list->left;
7028 form->top=list->top;
7029 form->right=list->right;
7030 form->bottom=list->bottom;
7033 /****************************************************************************
7034 ****************************************************************************/
7036 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7038 uint32 level = q_u->level;
7039 RPC_BUFFER *buffer = NULL;
7040 uint32 offered = q_u->offered;
7041 uint32 *needed = &r_u->needed;
7042 uint32 *numofforms = &r_u->numofforms;
7043 uint32 numbuiltinforms;
7045 nt_forms_struct *list=NULL;
7046 nt_forms_struct *builtinlist=NULL;
7047 FORM_1 *forms_1;
7048 int buffer_size=0;
7049 int i;
7051 /* that's an [in out] buffer */
7053 if ( q_u->buffer ) {
7054 rpcbuf_move(q_u->buffer, &r_u->buffer);
7055 buffer = r_u->buffer;
7058 DEBUG(4,("_spoolss_enumforms\n"));
7059 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7060 DEBUGADD(5,("Info level [%d]\n", level));
7062 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7063 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7064 *numofforms = get_ntforms(&list);
7065 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7066 *numofforms += numbuiltinforms;
7068 if (*numofforms == 0)
7069 return WERR_NO_MORE_ITEMS;
7071 switch (level) {
7072 case 1:
7073 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7074 *numofforms=0;
7075 return WERR_NOMEM;
7078 /* construct the list of form structures */
7079 for (i=0; i<numbuiltinforms; i++) {
7080 DEBUGADD(6,("Filling form number [%d]\n",i));
7081 fill_form_1(&forms_1[i], &builtinlist[i]);
7084 SAFE_FREE(builtinlist);
7086 for (; i<*numofforms; i++) {
7087 DEBUGADD(6,("Filling form number [%d]\n",i));
7088 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7091 SAFE_FREE(list);
7093 /* check the required size. */
7094 for (i=0; i<numbuiltinforms; i++) {
7095 DEBUGADD(6,("adding form [%d]'s size\n",i));
7096 buffer_size += spoolss_size_form_1(&forms_1[i]);
7098 for (; i<*numofforms; i++) {
7099 DEBUGADD(6,("adding form [%d]'s size\n",i));
7100 buffer_size += spoolss_size_form_1(&forms_1[i]);
7103 *needed=buffer_size;
7105 if (*needed > offered) {
7106 SAFE_FREE(forms_1);
7107 *numofforms=0;
7108 return WERR_INSUFFICIENT_BUFFER;
7111 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7112 SAFE_FREE(forms_1);
7113 *numofforms=0;
7114 return WERR_NOMEM;
7117 /* fill the buffer with the form structures */
7118 for (i=0; i<numbuiltinforms; i++) {
7119 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7120 smb_io_form_1("", buffer, &forms_1[i], 0);
7122 for (; i<*numofforms; i++) {
7123 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7124 smb_io_form_1("", buffer, &forms_1[i], 0);
7127 SAFE_FREE(forms_1);
7129 return WERR_OK;
7131 default:
7132 SAFE_FREE(list);
7133 SAFE_FREE(builtinlist);
7134 return WERR_UNKNOWN_LEVEL;
7139 /****************************************************************************
7140 ****************************************************************************/
7142 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7144 uint32 level = q_u->level;
7145 UNISTR2 *uni_formname = &q_u->formname;
7146 RPC_BUFFER *buffer = NULL;
7147 uint32 offered = q_u->offered;
7148 uint32 *needed = &r_u->needed;
7150 nt_forms_struct *list=NULL;
7151 nt_forms_struct builtin_form;
7152 BOOL foundBuiltin;
7153 FORM_1 form_1;
7154 fstring form_name;
7155 int buffer_size=0;
7156 int numofforms=0, i=0;
7158 /* that's an [in out] buffer */
7160 if ( q_u->buffer ) {
7161 rpcbuf_move(q_u->buffer, &r_u->buffer);
7162 buffer = r_u->buffer;
7165 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7167 DEBUG(4,("_spoolss_getform\n"));
7168 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7169 DEBUGADD(5,("Info level [%d]\n", level));
7171 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7172 if (!foundBuiltin) {
7173 numofforms = get_ntforms(&list);
7174 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7176 if (numofforms == 0)
7177 return WERR_BADFID;
7180 switch (level) {
7181 case 1:
7182 if (foundBuiltin) {
7183 fill_form_1(&form_1, &builtin_form);
7184 } else {
7186 /* Check if the requested name is in the list of form structures */
7187 for (i=0; i<numofforms; i++) {
7189 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7191 if (strequal(form_name, list[i].name)) {
7192 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7193 fill_form_1(&form_1, &list[i]);
7194 break;
7198 SAFE_FREE(list);
7199 if (i == numofforms) {
7200 return WERR_BADFID;
7203 /* check the required size. */
7205 *needed=spoolss_size_form_1(&form_1);
7207 if (*needed > offered)
7208 return WERR_INSUFFICIENT_BUFFER;
7210 if (!rpcbuf_alloc_size(buffer, buffer_size))
7211 return WERR_NOMEM;
7213 /* fill the buffer with the form structures */
7214 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7215 smb_io_form_1("", buffer, &form_1, 0);
7217 return WERR_OK;
7219 default:
7220 SAFE_FREE(list);
7221 return WERR_UNKNOWN_LEVEL;
7225 /****************************************************************************
7226 ****************************************************************************/
7228 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7230 init_unistr(&port->port_name, name);
7233 /****************************************************************************
7234 ****************************************************************************/
7236 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7238 init_unistr(&port->port_name, name);
7239 init_unistr(&port->monitor_name, "Local Monitor");
7240 init_unistr(&port->description, "Local Port");
7241 port->port_type=PORT_TYPE_WRITE;
7242 port->reserved=0x0;
7245 /****************************************************************************
7246 enumports level 1.
7247 ****************************************************************************/
7249 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7251 PORT_INFO_1 *ports=NULL;
7252 int i=0;
7253 WERROR result = WERR_OK;
7255 if (*lp_enumports_cmd()) {
7256 char *cmd = lp_enumports_cmd();
7257 char **qlines;
7258 pstring command;
7259 int numlines;
7260 int ret;
7261 int fd;
7263 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7265 DEBUG(10,("Running [%s]\n", command));
7266 ret = smbrun(command, &fd);
7267 DEBUG(10,("Returned [%d]\n", ret));
7268 if (ret != 0) {
7269 if (fd != -1)
7270 close(fd);
7271 /* Is this the best error to return here? */
7272 return WERR_ACCESS_DENIED;
7275 numlines = 0;
7276 qlines = fd_lines_load(fd, &numlines);
7277 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7278 close(fd);
7280 if(numlines) {
7281 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7282 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7283 dos_errstr(WERR_NOMEM)));
7284 file_lines_free(qlines);
7285 return WERR_NOMEM;
7288 for (i=0; i<numlines; i++) {
7289 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7290 fill_port_1(&ports[i], qlines[i]);
7293 file_lines_free(qlines);
7296 *returned = numlines;
7298 } else {
7299 *returned = 1; /* Sole Samba port returned. */
7301 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7302 return WERR_NOMEM;
7304 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7306 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7309 /* check the required size. */
7310 for (i=0; i<*returned; i++) {
7311 DEBUGADD(6,("adding port [%d]'s size\n", i));
7312 *needed += spoolss_size_port_info_1(&ports[i]);
7315 if (*needed > offered) {
7316 result = WERR_INSUFFICIENT_BUFFER;
7317 goto out;
7320 if (!rpcbuf_alloc_size(buffer, *needed)) {
7321 result = WERR_NOMEM;
7322 goto out;
7325 /* fill the buffer with the ports structures */
7326 for (i=0; i<*returned; i++) {
7327 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7328 smb_io_port_1("", buffer, &ports[i], 0);
7331 out:
7332 SAFE_FREE(ports);
7334 if ( !W_ERROR_IS_OK(result) )
7335 *returned = 0;
7337 return result;
7340 /****************************************************************************
7341 enumports level 2.
7342 ****************************************************************************/
7344 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7346 PORT_INFO_2 *ports=NULL;
7347 int i=0;
7348 WERROR result = WERR_OK;
7350 if (*lp_enumports_cmd()) {
7351 char *cmd = lp_enumports_cmd();
7352 char *path;
7353 char **qlines;
7354 pstring tmp_file;
7355 pstring command;
7356 int numlines;
7357 int ret;
7358 int fd;
7360 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7361 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7362 else
7363 path = lp_lockdir();
7365 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7366 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7368 unlink(tmp_file);
7369 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7370 ret = smbrun(command, &fd);
7371 DEBUGADD(10,("returned [%d]\n", ret));
7372 if (ret != 0) {
7373 if (fd != -1)
7374 close(fd);
7375 /* Is this the best error to return here? */
7376 return WERR_ACCESS_DENIED;
7379 numlines = 0;
7380 qlines = fd_lines_load(fd, &numlines);
7381 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7382 close(fd);
7384 if(numlines) {
7385 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7386 file_lines_free(qlines);
7387 return WERR_NOMEM;
7390 for (i=0; i<numlines; i++) {
7391 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7392 fill_port_2(&(ports[i]), qlines[i]);
7395 file_lines_free(qlines);
7398 *returned = numlines;
7400 } else {
7402 *returned = 1;
7404 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7405 return WERR_NOMEM;
7407 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7409 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7412 /* check the required size. */
7413 for (i=0; i<*returned; i++) {
7414 DEBUGADD(6,("adding port [%d]'s size\n", i));
7415 *needed += spoolss_size_port_info_2(&ports[i]);
7418 if (*needed > offered) {
7419 result = WERR_INSUFFICIENT_BUFFER;
7420 goto out;
7423 if (!rpcbuf_alloc_size(buffer, *needed)) {
7424 result = WERR_NOMEM;
7425 goto out;
7428 /* fill the buffer with the ports structures */
7429 for (i=0; i<*returned; i++) {
7430 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7431 smb_io_port_2("", buffer, &ports[i], 0);
7434 out:
7435 SAFE_FREE(ports);
7437 if ( !W_ERROR_IS_OK(result) )
7438 *returned = 0;
7440 return result;
7443 /****************************************************************************
7444 enumports.
7445 ****************************************************************************/
7447 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7449 uint32 level = q_u->level;
7450 RPC_BUFFER *buffer = NULL;
7451 uint32 offered = q_u->offered;
7452 uint32 *needed = &r_u->needed;
7453 uint32 *returned = &r_u->returned;
7455 /* that's an [in out] buffer */
7457 if ( q_u->buffer ) {
7458 rpcbuf_move(q_u->buffer, &r_u->buffer);
7459 buffer = r_u->buffer;
7462 DEBUG(4,("_spoolss_enumports\n"));
7464 *returned=0;
7465 *needed=0;
7467 switch (level) {
7468 case 1:
7469 return enumports_level_1(buffer, offered, needed, returned);
7470 case 2:
7471 return enumports_level_2(buffer, offered, needed, returned);
7472 default:
7473 return WERR_UNKNOWN_LEVEL;
7477 /****************************************************************************
7478 ****************************************************************************/
7480 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7481 const SPOOL_PRINTER_INFO_LEVEL *info,
7482 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7483 uint32 user_switch, const SPOOL_USER_CTR *user,
7484 POLICY_HND *handle)
7486 NT_PRINTER_INFO_LEVEL *printer = NULL;
7487 fstring name;
7488 int snum;
7489 WERROR err = WERR_OK;
7491 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7492 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7493 return WERR_NOMEM;
7496 ZERO_STRUCTP(printer);
7498 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7499 if (!convert_printer_info(info, printer, 2)) {
7500 free_a_printer(&printer, 2);
7501 return WERR_NOMEM;
7504 /* check to see if the printer already exists */
7506 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7507 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7508 printer->info_2->sharename));
7509 free_a_printer(&printer, 2);
7510 return WERR_PRINTER_ALREADY_EXISTS;
7513 /* FIXME!!! smbd should check to see if the driver is installed before
7514 trying to add a printer like this --jerry */
7516 if (*lp_addprinter_cmd() ) {
7517 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7518 free_a_printer(&printer,2);
7519 return WERR_ACCESS_DENIED;
7523 /* use our primary netbios name since get_a_printer() will convert
7524 it to what the client expects on a case by case basis */
7526 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7527 printer->info_2->sharename);
7530 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7531 free_a_printer(&printer,2);
7532 return WERR_ACCESS_DENIED;
7535 /* you must be a printer admin to add a new printer */
7536 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7537 free_a_printer(&printer,2);
7538 return WERR_ACCESS_DENIED;
7542 * Do sanity check on the requested changes for Samba.
7545 if (!check_printer_ok(printer->info_2, snum)) {
7546 free_a_printer(&printer,2);
7547 return WERR_INVALID_PARAM;
7551 * When a printer is created, the drivername bound to the printer is used
7552 * to lookup previously saved driver initialization info, which is then
7553 * bound to the new printer, simulating what happens in the Windows arch.
7556 if (!devmode)
7558 set_driver_init(printer, 2);
7560 else
7562 /* A valid devmode was included, convert and link it
7564 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7566 if (!convert_devicemode(printer->info_2->printername, devmode,
7567 &printer->info_2->devmode))
7568 return WERR_NOMEM;
7571 /* write the ASCII on disk */
7572 err = mod_a_printer(printer, 2);
7573 if (!W_ERROR_IS_OK(err)) {
7574 free_a_printer(&printer,2);
7575 return err;
7578 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7579 /* Handle open failed - remove addition. */
7580 del_a_printer(printer->info_2->sharename);
7581 free_a_printer(&printer,2);
7582 return WERR_ACCESS_DENIED;
7585 update_c_setprinter(False);
7586 free_a_printer(&printer,2);
7588 return WERR_OK;
7591 /****************************************************************************
7592 ****************************************************************************/
7594 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7596 UNISTR2 *uni_srv_name = q_u->server_name;
7597 uint32 level = q_u->level;
7598 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7599 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7600 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7601 uint32 user_switch = q_u->user_switch;
7602 SPOOL_USER_CTR *user = &q_u->user_ctr;
7603 POLICY_HND *handle = &r_u->handle;
7605 switch (level) {
7606 case 1:
7607 /* we don't handle yet */
7608 /* but I know what to do ... */
7609 return WERR_UNKNOWN_LEVEL;
7610 case 2:
7611 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7612 devmode, sdb,
7613 user_switch, user, handle);
7614 default:
7615 return WERR_UNKNOWN_LEVEL;
7619 /****************************************************************************
7620 ****************************************************************************/
7622 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7624 uint32 level = q_u->level;
7625 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7626 WERROR err = WERR_OK;
7627 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7628 struct current_user user;
7629 fstring driver_name;
7630 uint32 version;
7632 ZERO_STRUCT(driver);
7634 get_current_user(&user, p);
7636 if (!convert_printer_driver_info(info, &driver, level)) {
7637 err = WERR_NOMEM;
7638 goto done;
7641 DEBUG(5,("Cleaning driver's information\n"));
7642 err = clean_up_driver_struct(driver, level, &user);
7643 if (!W_ERROR_IS_OK(err))
7644 goto done;
7646 DEBUG(5,("Moving driver to final destination\n"));
7647 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7648 if (W_ERROR_IS_OK(err))
7649 err = WERR_ACCESS_DENIED;
7650 goto done;
7653 if (add_a_printer_driver(driver, level)!=0) {
7654 err = WERR_ACCESS_DENIED;
7655 goto done;
7658 /* BEGIN_ADMIN_LOG */
7659 switch(level) {
7660 case 3:
7661 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7662 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7663 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7664 break;
7665 case 6:
7666 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7667 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7668 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7669 break;
7671 /* END_ADMIN_LOG */
7674 * I think this is where he DrvUpgradePrinter() hook would be
7675 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7676 * server. Right now, we just need to send ourselves a message
7677 * to update each printer bound to this driver. --jerry
7680 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7681 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7682 driver_name));
7686 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7687 * decide if the driver init data should be deleted. The rules are:
7688 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7689 * 2) delete init data only if there is no 2k/Xp driver
7690 * 3) always delete init data
7691 * The generalized rule is always use init data from the highest order driver.
7692 * It is necessary to follow the driver install by an initialization step to
7693 * finish off this process.
7695 if (level == 3)
7696 version = driver.info_3->cversion;
7697 else if (level == 6)
7698 version = driver.info_6->version;
7699 else
7700 version = -1;
7701 switch (version) {
7703 * 9x printer driver - never delete init data
7705 case 0:
7706 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7707 driver_name));
7708 break;
7711 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7712 * there is no 2k/Xp driver init data for this driver name.
7714 case 2:
7716 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7718 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7720 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7722 if (!del_driver_init(driver_name))
7723 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7724 } else {
7726 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7728 free_a_printer_driver(driver1,3);
7729 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7730 driver_name));
7733 break;
7736 * 2k or Xp printer driver - always delete init data
7738 case 3:
7739 if (!del_driver_init(driver_name))
7740 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7741 break;
7743 default:
7744 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7745 break;
7749 done:
7750 free_a_printer_driver(driver, level);
7751 return err;
7754 /********************************************************************
7755 * spoolss_addprinterdriverex
7756 ********************************************************************/
7758 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7760 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7761 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7764 * we only support the semantics of AddPrinterDriver()
7765 * i.e. only copy files that are newer than existing ones
7768 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7769 return WERR_ACCESS_DENIED;
7771 ZERO_STRUCT(q_u_local);
7772 ZERO_STRUCT(r_u_local);
7774 /* just pass the information off to _spoolss_addprinterdriver() */
7775 q_u_local.server_name_ptr = q_u->server_name_ptr;
7776 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7777 q_u_local.level = q_u->level;
7778 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7780 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7783 /****************************************************************************
7784 ****************************************************************************/
7786 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7788 init_unistr(&info->name, name);
7791 /****************************************************************************
7792 ****************************************************************************/
7794 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7796 pstring path;
7797 pstring long_archi;
7798 fstring servername;
7799 char *pservername;
7800 const char *short_archi;
7801 DRIVER_DIRECTORY_1 *info=NULL;
7802 WERROR result = WERR_OK;
7804 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7805 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7807 /* check for beginning double '\'s and that the server
7808 long enough */
7810 pservername = servername;
7811 if ( *pservername == '\\' && strlen(servername)>2 ) {
7812 pservername += 2;
7815 if ( !is_myname_or_ipaddr( pservername ) )
7816 return WERR_INVALID_PARAM;
7818 if (!(short_archi = get_short_archi(long_archi)))
7819 return WERR_INVALID_ENVIRONMENT;
7821 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7822 return WERR_NOMEM;
7824 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7826 DEBUG(4,("printer driver directory: [%s]\n", path));
7828 fill_driverdir_1(info, path);
7830 *needed += spoolss_size_driverdir_info_1(info);
7832 if (*needed > offered) {
7833 result = WERR_INSUFFICIENT_BUFFER;
7834 goto out;
7837 if (!rpcbuf_alloc_size(buffer, *needed)) {
7838 result = WERR_NOMEM;
7839 goto out;
7842 smb_io_driverdir_1("", buffer, info, 0);
7844 out:
7845 SAFE_FREE(info);
7847 return result;
7850 /****************************************************************************
7851 ****************************************************************************/
7853 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7855 UNISTR2 *name = &q_u->name;
7856 UNISTR2 *uni_environment = &q_u->environment;
7857 uint32 level = q_u->level;
7858 RPC_BUFFER *buffer = NULL;
7859 uint32 offered = q_u->offered;
7860 uint32 *needed = &r_u->needed;
7862 /* that's an [in out] buffer */
7864 if ( q_u->buffer ) {
7865 rpcbuf_move(q_u->buffer, &r_u->buffer);
7866 buffer = r_u->buffer;
7869 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7871 *needed=0;
7873 switch(level) {
7874 case 1:
7875 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7876 default:
7877 return WERR_UNKNOWN_LEVEL;
7881 /****************************************************************************
7882 ****************************************************************************/
7884 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7886 POLICY_HND *handle = &q_u->handle;
7887 uint32 idx = q_u->index;
7888 uint32 in_value_len = q_u->valuesize;
7889 uint32 in_data_len = q_u->datasize;
7890 uint32 *out_max_value_len = &r_u->valuesize;
7891 uint16 **out_value = &r_u->value;
7892 uint32 *out_value_len = &r_u->realvaluesize;
7893 uint32 *out_type = &r_u->type;
7894 uint32 *out_max_data_len = &r_u->datasize;
7895 uint8 **data_out = &r_u->data;
7896 uint32 *out_data_len = &r_u->realdatasize;
7898 NT_PRINTER_INFO_LEVEL *printer = NULL;
7900 uint32 biggest_valuesize;
7901 uint32 biggest_datasize;
7902 uint32 data_len;
7903 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7904 int snum;
7905 WERROR result;
7906 REGISTRY_VALUE *val = NULL;
7907 NT_PRINTER_DATA *p_data;
7908 int i, key_index, num_values;
7909 int name_length;
7911 ZERO_STRUCT( printer );
7913 *out_type = 0;
7915 *out_max_data_len = 0;
7916 *data_out = NULL;
7917 *out_data_len = 0;
7919 DEBUG(5,("spoolss_enumprinterdata\n"));
7921 if (!Printer) {
7922 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7923 return WERR_BADFID;
7926 if (!get_printer_snum(p,handle, &snum))
7927 return WERR_BADFID;
7929 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7930 if (!W_ERROR_IS_OK(result))
7931 return result;
7933 p_data = &printer->info_2->data;
7934 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7936 result = WERR_OK;
7939 * The NT machine wants to know the biggest size of value and data
7941 * cf: MSDN EnumPrinterData remark section
7944 if ( !in_value_len && !in_data_len && (key_index != -1) )
7946 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7948 biggest_valuesize = 0;
7949 biggest_datasize = 0;
7951 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7953 for ( i=0; i<num_values; i++ )
7955 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7957 name_length = strlen(val->valuename);
7958 if ( strlen(val->valuename) > biggest_valuesize )
7959 biggest_valuesize = name_length;
7961 if ( val->size > biggest_datasize )
7962 biggest_datasize = val->size;
7964 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7965 biggest_datasize));
7968 /* the value is an UNICODE string but real_value_size is the length
7969 in bytes including the trailing 0 */
7971 *out_value_len = 2 * (1+biggest_valuesize);
7972 *out_data_len = biggest_datasize;
7974 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7976 goto done;
7980 * the value len is wrong in NT sp3
7981 * that's the number of bytes not the number of unicode chars
7984 if ( key_index != -1 )
7985 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7987 if ( !val )
7990 /* out_value should default to "" or else NT4 has
7991 problems unmarshalling the response */
7993 *out_max_value_len=(in_value_len/sizeof(uint16));
7995 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7997 result = WERR_NOMEM;
7998 goto done;
8001 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8003 /* the data is counted in bytes */
8005 *out_max_data_len = in_data_len;
8006 *out_data_len = in_data_len;
8008 /* only allocate when given a non-zero data_len */
8010 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8012 result = WERR_NOMEM;
8013 goto done;
8016 result = WERR_NO_MORE_ITEMS;
8018 else
8021 * the value is:
8022 * - counted in bytes in the request
8023 * - counted in UNICODE chars in the max reply
8024 * - counted in bytes in the real size
8026 * take a pause *before* coding not *during* coding
8029 /* name */
8030 *out_max_value_len=(in_value_len/sizeof(uint16));
8031 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8033 result = WERR_NOMEM;
8034 goto done;
8037 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
8039 /* type */
8041 *out_type = regval_type( val );
8043 /* data - counted in bytes */
8045 *out_max_data_len = in_data_len;
8046 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8048 result = WERR_NOMEM;
8049 goto done;
8051 data_len = (size_t)regval_size(val);
8052 memcpy( *data_out, regval_data_p(val), data_len );
8053 *out_data_len = data_len;
8056 done:
8057 free_a_printer(&printer, 2);
8058 return result;
8061 /****************************************************************************
8062 ****************************************************************************/
8064 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8066 POLICY_HND *handle = &q_u->handle;
8067 UNISTR2 *value = &q_u->value;
8068 uint32 type = q_u->type;
8069 uint8 *data = q_u->data;
8070 uint32 real_len = q_u->real_len;
8072 NT_PRINTER_INFO_LEVEL *printer = NULL;
8073 int snum=0;
8074 WERROR status = WERR_OK;
8075 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8076 fstring valuename;
8078 DEBUG(5,("spoolss_setprinterdata\n"));
8080 if (!Printer) {
8081 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8082 return WERR_BADFID;
8085 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8086 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8087 return WERR_INVALID_PARAM;
8090 if (!get_printer_snum(p,handle, &snum))
8091 return WERR_BADFID;
8094 * Access check : NT returns "access denied" if you make a
8095 * SetPrinterData call without the necessary privildge.
8096 * we were originally returning OK if nothing changed
8097 * which made Win2k issue **a lot** of SetPrinterData
8098 * when connecting to a printer --jerry
8101 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8103 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8104 status = WERR_ACCESS_DENIED;
8105 goto done;
8108 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8109 if (!W_ERROR_IS_OK(status))
8110 return status;
8112 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8115 * When client side code sets a magic printer data key, detect it and save
8116 * the current printer data and the magic key's data (its the DEVMODE) for
8117 * future printer/driver initializations.
8119 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8121 /* Set devmode and printer initialization info */
8122 status = save_driver_init( printer, 2, data, real_len );
8124 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8126 else
8128 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8129 type, data, real_len );
8130 if ( W_ERROR_IS_OK(status) )
8131 status = mod_a_printer(printer, 2);
8134 done:
8135 free_a_printer(&printer, 2);
8137 return status;
8140 /****************************************************************************
8141 ****************************************************************************/
8143 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8145 POLICY_HND *handle = &q_u->handle;
8146 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8147 int snum;
8149 DEBUG(5,("_spoolss_resetprinter\n"));
8152 * All we do is to check to see if the handle and queue is valid.
8153 * This call really doesn't mean anything to us because we only
8154 * support RAW printing. --jerry
8157 if (!Printer) {
8158 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8159 return WERR_BADFID;
8162 if (!get_printer_snum(p,handle, &snum))
8163 return WERR_BADFID;
8166 /* blindly return success */
8167 return WERR_OK;
8171 /****************************************************************************
8172 ****************************************************************************/
8174 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8176 POLICY_HND *handle = &q_u->handle;
8177 UNISTR2 *value = &q_u->valuename;
8179 NT_PRINTER_INFO_LEVEL *printer = NULL;
8180 int snum=0;
8181 WERROR status = WERR_OK;
8182 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8183 pstring valuename;
8185 DEBUG(5,("spoolss_deleteprinterdata\n"));
8187 if (!Printer) {
8188 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8189 return WERR_BADFID;
8192 if (!get_printer_snum(p, handle, &snum))
8193 return WERR_BADFID;
8195 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8196 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8197 return WERR_ACCESS_DENIED;
8200 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8201 if (!W_ERROR_IS_OK(status))
8202 return status;
8204 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8206 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8208 if ( W_ERROR_IS_OK(status) )
8209 mod_a_printer( printer, 2 );
8211 free_a_printer(&printer, 2);
8213 return status;
8216 /****************************************************************************
8217 ****************************************************************************/
8219 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8221 POLICY_HND *handle = &q_u->handle;
8222 FORM *form = &q_u->form;
8223 nt_forms_struct tmpForm;
8224 int snum;
8225 WERROR status = WERR_OK;
8226 NT_PRINTER_INFO_LEVEL *printer = NULL;
8228 int count=0;
8229 nt_forms_struct *list=NULL;
8230 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8232 DEBUG(5,("spoolss_addform\n"));
8234 if (!Printer) {
8235 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8236 return WERR_BADFID;
8240 /* forms can be added on printer of on the print server handle */
8242 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8244 if (!get_printer_snum(p,handle, &snum))
8245 return WERR_BADFID;
8247 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8248 if (!W_ERROR_IS_OK(status))
8249 goto done;
8252 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8253 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8254 status = WERR_ACCESS_DENIED;
8255 goto done;
8258 /* can't add if builtin */
8260 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8261 status = WERR_ALREADY_EXISTS;
8262 goto done;
8265 count = get_ntforms(&list);
8267 if(!add_a_form(&list, form, &count)) {
8268 status = WERR_NOMEM;
8269 goto done;
8272 write_ntforms(&list, count);
8275 * ChangeID must always be set if this is a printer
8278 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8279 status = mod_a_printer(printer, 2);
8281 done:
8282 if ( printer )
8283 free_a_printer(&printer, 2);
8284 SAFE_FREE(list);
8286 return status;
8289 /****************************************************************************
8290 ****************************************************************************/
8292 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8294 POLICY_HND *handle = &q_u->handle;
8295 UNISTR2 *form_name = &q_u->name;
8296 nt_forms_struct tmpForm;
8297 int count=0;
8298 nt_forms_struct *list=NULL;
8299 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8300 int snum;
8301 WERROR status = WERR_OK;
8302 NT_PRINTER_INFO_LEVEL *printer = NULL;
8304 DEBUG(5,("spoolss_deleteform\n"));
8306 if (!Printer) {
8307 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8308 return WERR_BADFID;
8311 /* forms can be deleted on printer of on the print server handle */
8313 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8315 if (!get_printer_snum(p,handle, &snum))
8316 return WERR_BADFID;
8318 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8319 if (!W_ERROR_IS_OK(status))
8320 goto done;
8323 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8324 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8325 status = WERR_ACCESS_DENIED;
8326 goto done;
8329 /* can't delete if builtin */
8331 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8332 status = WERR_INVALID_PARAM;
8333 goto done;
8336 count = get_ntforms(&list);
8338 if ( !delete_a_form(&list, form_name, &count, &status ))
8339 goto done;
8342 * ChangeID must always be set if this is a printer
8345 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8346 status = mod_a_printer(printer, 2);
8348 done:
8349 if ( printer )
8350 free_a_printer(&printer, 2);
8351 SAFE_FREE(list);
8353 return status;
8356 /****************************************************************************
8357 ****************************************************************************/
8359 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8361 POLICY_HND *handle = &q_u->handle;
8362 FORM *form = &q_u->form;
8363 nt_forms_struct tmpForm;
8364 int snum;
8365 WERROR status = WERR_OK;
8366 NT_PRINTER_INFO_LEVEL *printer = NULL;
8368 int count=0;
8369 nt_forms_struct *list=NULL;
8370 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8372 DEBUG(5,("spoolss_setform\n"));
8374 if (!Printer) {
8375 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8376 return WERR_BADFID;
8379 /* forms can be modified on printer of on the print server handle */
8381 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8383 if (!get_printer_snum(p,handle, &snum))
8384 return WERR_BADFID;
8386 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8387 if (!W_ERROR_IS_OK(status))
8388 goto done;
8391 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8392 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8393 status = WERR_ACCESS_DENIED;
8394 goto done;
8397 /* can't set if builtin */
8398 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8399 status = WERR_INVALID_PARAM;
8400 goto done;
8403 count = get_ntforms(&list);
8404 update_a_form(&list, form, count);
8405 write_ntforms(&list, count);
8408 * ChangeID must always be set if this is a printer
8411 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8412 status = mod_a_printer(printer, 2);
8415 done:
8416 if ( printer )
8417 free_a_printer(&printer, 2);
8418 SAFE_FREE(list);
8420 return status;
8423 /****************************************************************************
8424 enumprintprocessors level 1.
8425 ****************************************************************************/
8427 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8429 PRINTPROCESSOR_1 *info_1=NULL;
8430 WERROR result = WERR_OK;
8432 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8433 return WERR_NOMEM;
8435 (*returned) = 0x1;
8437 init_unistr(&info_1->name, "winprint");
8439 *needed += spoolss_size_printprocessor_info_1(info_1);
8441 if (*needed > offered) {
8442 result = WERR_INSUFFICIENT_BUFFER;
8443 goto out;
8446 if (!rpcbuf_alloc_size(buffer, *needed)) {
8447 result = WERR_NOMEM;
8448 goto out;
8451 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8453 out:
8454 SAFE_FREE(info_1);
8456 if ( !W_ERROR_IS_OK(result) )
8457 *returned = 0;
8459 return result;
8462 /****************************************************************************
8463 ****************************************************************************/
8465 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8467 uint32 level = q_u->level;
8468 RPC_BUFFER *buffer = NULL;
8469 uint32 offered = q_u->offered;
8470 uint32 *needed = &r_u->needed;
8471 uint32 *returned = &r_u->returned;
8473 /* that's an [in out] buffer */
8475 if ( q_u->buffer ) {
8476 rpcbuf_move(q_u->buffer, &r_u->buffer);
8477 buffer = r_u->buffer;
8480 DEBUG(5,("spoolss_enumprintprocessors\n"));
8483 * Enumerate the print processors ...
8485 * Just reply with "winprint", to keep NT happy
8486 * and I can use my nice printer checker.
8489 *returned=0;
8490 *needed=0;
8492 switch (level) {
8493 case 1:
8494 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8495 default:
8496 return WERR_UNKNOWN_LEVEL;
8500 /****************************************************************************
8501 enumprintprocdatatypes level 1.
8502 ****************************************************************************/
8504 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8506 PRINTPROCDATATYPE_1 *info_1=NULL;
8507 WERROR result = WERR_NOMEM;
8509 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8510 return WERR_NOMEM;
8512 (*returned) = 0x1;
8514 init_unistr(&info_1->name, "RAW");
8516 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8518 if (*needed > offered) {
8519 result = WERR_INSUFFICIENT_BUFFER;
8520 goto out;
8523 if (!rpcbuf_alloc_size(buffer, *needed)) {
8524 result = WERR_NOMEM;
8525 goto out;
8528 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8530 out:
8531 SAFE_FREE(info_1);
8533 if ( !W_ERROR_IS_OK(result) )
8534 *returned = 0;
8536 return result;
8539 /****************************************************************************
8540 ****************************************************************************/
8542 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8544 uint32 level = q_u->level;
8545 RPC_BUFFER *buffer = NULL;
8546 uint32 offered = q_u->offered;
8547 uint32 *needed = &r_u->needed;
8548 uint32 *returned = &r_u->returned;
8550 /* that's an [in out] buffer */
8552 if ( q_u->buffer ) {
8553 rpcbuf_move(q_u->buffer, &r_u->buffer);
8554 buffer = r_u->buffer;
8557 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8559 *returned=0;
8560 *needed=0;
8562 switch (level) {
8563 case 1:
8564 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8565 default:
8566 return WERR_UNKNOWN_LEVEL;
8570 /****************************************************************************
8571 enumprintmonitors level 1.
8572 ****************************************************************************/
8574 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8576 PRINTMONITOR_1 *info_1=NULL;
8577 WERROR result = WERR_OK;
8579 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8580 return WERR_NOMEM;
8582 (*returned) = 0x1;
8584 init_unistr(&info_1->name, "Local Port");
8586 *needed += spoolss_size_printmonitor_info_1(info_1);
8588 if (*needed > offered) {
8589 result = WERR_INSUFFICIENT_BUFFER;
8590 goto out;
8593 if (!rpcbuf_alloc_size(buffer, *needed)) {
8594 result = WERR_NOMEM;
8595 goto out;
8598 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8600 out:
8601 SAFE_FREE(info_1);
8603 if ( !W_ERROR_IS_OK(result) )
8604 *returned = 0;
8606 return result;
8609 /****************************************************************************
8610 enumprintmonitors level 2.
8611 ****************************************************************************/
8613 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8615 PRINTMONITOR_2 *info_2=NULL;
8616 WERROR result = WERR_OK;
8618 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8619 return WERR_NOMEM;
8621 (*returned) = 0x1;
8623 init_unistr(&info_2->name, "Local Port");
8624 init_unistr(&info_2->environment, "Windows NT X86");
8625 init_unistr(&info_2->dll_name, "localmon.dll");
8627 *needed += spoolss_size_printmonitor_info_2(info_2);
8629 if (*needed > offered) {
8630 result = WERR_INSUFFICIENT_BUFFER;
8631 goto out;
8634 if (!rpcbuf_alloc_size(buffer, *needed)) {
8635 result = WERR_NOMEM;
8636 goto out;
8639 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8641 out:
8642 SAFE_FREE(info_2);
8644 if ( !W_ERROR_IS_OK(result) )
8645 *returned = 0;
8647 return result;
8650 /****************************************************************************
8651 ****************************************************************************/
8653 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8655 uint32 level = q_u->level;
8656 RPC_BUFFER *buffer = NULL;
8657 uint32 offered = q_u->offered;
8658 uint32 *needed = &r_u->needed;
8659 uint32 *returned = &r_u->returned;
8661 /* that's an [in out] buffer */
8663 if ( q_u->buffer ) {
8664 rpcbuf_move(q_u->buffer, &r_u->buffer);
8665 buffer = r_u->buffer;
8668 DEBUG(5,("spoolss_enumprintmonitors\n"));
8671 * Enumerate the print monitors ...
8673 * Just reply with "Local Port", to keep NT happy
8674 * and I can use my nice printer checker.
8677 *returned=0;
8678 *needed=0;
8680 switch (level) {
8681 case 1:
8682 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8683 case 2:
8684 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8685 default:
8686 return WERR_UNKNOWN_LEVEL;
8690 /****************************************************************************
8691 ****************************************************************************/
8693 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8694 NT_PRINTER_INFO_LEVEL *ntprinter,
8695 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8696 uint32 *needed)
8698 int i=0;
8699 BOOL found=False;
8700 JOB_INFO_1 *info_1=NULL;
8701 WERROR result = WERR_OK;
8703 info_1=SMB_MALLOC_P(JOB_INFO_1);
8705 if (info_1 == NULL) {
8706 return WERR_NOMEM;
8709 for (i=0; i<count && found==False; i++) {
8710 if ((*queue)[i].job==(int)jobid)
8711 found=True;
8714 if (found==False) {
8715 SAFE_FREE(info_1);
8716 /* NT treats not found as bad param... yet another bad choice */
8717 return WERR_INVALID_PARAM;
8720 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8722 *needed += spoolss_size_job_info_1(info_1);
8724 if (*needed > offered) {
8725 result = WERR_INSUFFICIENT_BUFFER;
8726 goto out;
8729 if (!rpcbuf_alloc_size(buffer, *needed)) {
8730 result = WERR_NOMEM;
8731 goto out;
8734 smb_io_job_info_1("", buffer, info_1, 0);
8736 out:
8737 SAFE_FREE(info_1);
8739 return result;
8742 /****************************************************************************
8743 ****************************************************************************/
8745 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8746 NT_PRINTER_INFO_LEVEL *ntprinter,
8747 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8748 uint32 *needed)
8750 int i = 0;
8751 BOOL found = False;
8752 JOB_INFO_2 *info_2;
8753 WERROR result;
8754 DEVICEMODE *devmode = NULL;
8755 NT_DEVICEMODE *nt_devmode = NULL;
8757 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8758 return WERR_NOMEM;
8760 ZERO_STRUCTP(info_2);
8762 for ( i=0; i<count && found==False; i++ )
8764 if ((*queue)[i].job == (int)jobid)
8765 found = True;
8768 if ( !found ) {
8769 /* NT treats not found as bad param... yet another bad
8770 choice */
8771 result = WERR_INVALID_PARAM;
8772 goto done;
8776 * if the print job does not have a DEVMODE associated with it,
8777 * just use the one for the printer. A NULL devicemode is not
8778 * a failure condition
8781 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8782 devmode = construct_dev_mode(snum);
8783 else {
8784 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8785 ZERO_STRUCTP( devmode );
8786 convert_nt_devicemode( devmode, nt_devmode );
8790 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8792 *needed += spoolss_size_job_info_2(info_2);
8794 if (*needed > offered) {
8795 result = WERR_INSUFFICIENT_BUFFER;
8796 goto done;
8799 if (!rpcbuf_alloc_size(buffer, *needed)) {
8800 result = WERR_NOMEM;
8801 goto done;
8804 smb_io_job_info_2("", buffer, info_2, 0);
8806 result = WERR_OK;
8808 done:
8809 /* Cleanup allocated memory */
8811 free_job_info_2(info_2); /* Also frees devmode */
8812 SAFE_FREE(info_2);
8814 return result;
8817 /****************************************************************************
8818 ****************************************************************************/
8820 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8822 POLICY_HND *handle = &q_u->handle;
8823 uint32 jobid = q_u->jobid;
8824 uint32 level = q_u->level;
8825 RPC_BUFFER *buffer = NULL;
8826 uint32 offered = q_u->offered;
8827 uint32 *needed = &r_u->needed;
8828 WERROR wstatus = WERR_OK;
8829 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8830 int snum;
8831 int count;
8832 print_queue_struct *queue = NULL;
8833 print_status_struct prt_status;
8835 /* that's an [in out] buffer */
8837 if ( q_u->buffer ) {
8838 rpcbuf_move(q_u->buffer, &r_u->buffer);
8839 buffer = r_u->buffer;
8842 DEBUG(5,("spoolss_getjob\n"));
8844 *needed = 0;
8846 if (!get_printer_snum(p, handle, &snum))
8847 return WERR_BADFID;
8849 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8850 if ( !W_ERROR_IS_OK(wstatus) )
8851 return wstatus;
8853 count = print_queue_status(snum, &queue, &prt_status);
8855 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8856 count, prt_status.status, prt_status.message));
8858 switch ( level ) {
8859 case 1:
8860 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8861 buffer, offered, needed);
8862 break;
8863 case 2:
8864 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8865 buffer, offered, needed);
8866 break;
8867 default:
8868 wstatus = WERR_UNKNOWN_LEVEL;
8869 break;
8872 SAFE_FREE(queue);
8873 free_a_printer( &ntprinter, 2 );
8875 return wstatus;
8878 /********************************************************************
8879 spoolss_getprinterdataex
8881 From MSDN documentation of GetPrinterDataEx: pass request
8882 to GetPrinterData if key is "PrinterDriverData".
8883 ********************************************************************/
8885 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8887 POLICY_HND *handle = &q_u->handle;
8888 uint32 in_size = q_u->size;
8889 uint32 *type = &r_u->type;
8890 uint32 *out_size = &r_u->size;
8891 uint8 **data = &r_u->data;
8892 uint32 *needed = &r_u->needed;
8893 fstring keyname, valuename;
8895 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8897 NT_PRINTER_INFO_LEVEL *printer = NULL;
8898 int snum = 0;
8899 WERROR status = WERR_OK;
8901 DEBUG(4,("_spoolss_getprinterdataex\n"));
8903 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8904 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8906 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8907 keyname, valuename));
8909 /* in case of problem, return some default values */
8911 *needed = 0;
8912 *type = 0;
8913 *out_size = in_size;
8915 if (!Printer) {
8916 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8917 status = WERR_BADFID;
8918 goto done;
8921 /* Is the handle to a printer or to the server? */
8923 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8924 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8925 status = WERR_INVALID_PARAM;
8926 goto done;
8929 if ( !get_printer_snum(p,handle, &snum) )
8930 return WERR_BADFID;
8932 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8933 if ( !W_ERROR_IS_OK(status) )
8934 goto done;
8936 /* check to see if the keyname is valid */
8937 if ( !strlen(keyname) ) {
8938 status = WERR_INVALID_PARAM;
8939 goto done;
8942 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8943 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8944 free_a_printer( &printer, 2 );
8945 status = WERR_BADFILE;
8946 goto done;
8949 /* When given a new keyname, we should just create it */
8951 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8953 if (*needed > *out_size)
8954 status = WERR_MORE_DATA;
8956 done:
8957 if ( !W_ERROR_IS_OK(status) )
8959 DEBUG(5, ("error: allocating %d\n", *out_size));
8961 /* reply this param doesn't exist */
8963 if ( *out_size )
8965 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8966 status = WERR_NOMEM;
8967 goto done;
8970 else {
8971 *data = NULL;
8975 if ( printer )
8976 free_a_printer( &printer, 2 );
8978 return status;
8981 /********************************************************************
8982 * spoolss_setprinterdataex
8983 ********************************************************************/
8985 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8987 POLICY_HND *handle = &q_u->handle;
8988 uint32 type = q_u->type;
8989 uint8 *data = q_u->data;
8990 uint32 real_len = q_u->real_len;
8992 NT_PRINTER_INFO_LEVEL *printer = NULL;
8993 int snum = 0;
8994 WERROR status = WERR_OK;
8995 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8996 fstring valuename;
8997 fstring keyname;
8998 char *oid_string;
9000 DEBUG(4,("_spoolss_setprinterdataex\n"));
9002 /* From MSDN documentation of SetPrinterDataEx: pass request to
9003 SetPrinterData if key is "PrinterDriverData" */
9005 if (!Printer) {
9006 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9007 return WERR_BADFID;
9010 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
9011 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9012 return WERR_INVALID_PARAM;
9015 if ( !get_printer_snum(p,handle, &snum) )
9016 return WERR_BADFID;
9019 * Access check : NT returns "access denied" if you make a
9020 * SetPrinterData call without the necessary privildge.
9021 * we were originally returning OK if nothing changed
9022 * which made Win2k issue **a lot** of SetPrinterData
9023 * when connecting to a printer --jerry
9026 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9028 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9029 return WERR_ACCESS_DENIED;
9032 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9033 if (!W_ERROR_IS_OK(status))
9034 return status;
9036 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9037 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9039 /* check for OID in valuename */
9041 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9043 *oid_string = '\0';
9044 oid_string++;
9047 /* save the registry data */
9049 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9051 if ( W_ERROR_IS_OK(status) )
9053 /* save the OID if one was specified */
9054 if ( oid_string ) {
9055 fstrcat( keyname, "\\" );
9056 fstrcat( keyname, SPOOL_OID_KEY );
9059 * I'm not checking the status here on purpose. Don't know
9060 * if this is right, but I'm returning the status from the
9061 * previous set_printer_dataex() call. I have no idea if
9062 * this is right. --jerry
9065 set_printer_dataex( printer, keyname, valuename,
9066 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9069 status = mod_a_printer(printer, 2);
9072 free_a_printer(&printer, 2);
9074 return status;
9078 /********************************************************************
9079 * spoolss_deleteprinterdataex
9080 ********************************************************************/
9082 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9084 POLICY_HND *handle = &q_u->handle;
9085 UNISTR2 *value = &q_u->valuename;
9086 UNISTR2 *key = &q_u->keyname;
9088 NT_PRINTER_INFO_LEVEL *printer = NULL;
9089 int snum=0;
9090 WERROR status = WERR_OK;
9091 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9092 pstring valuename, keyname;
9094 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9096 if (!Printer) {
9097 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9098 return WERR_BADFID;
9101 if (!get_printer_snum(p, handle, &snum))
9102 return WERR_BADFID;
9104 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9105 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9106 return WERR_ACCESS_DENIED;
9109 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9110 if (!W_ERROR_IS_OK(status))
9111 return status;
9113 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9114 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9116 status = delete_printer_dataex( printer, keyname, valuename );
9118 if ( W_ERROR_IS_OK(status) )
9119 mod_a_printer( printer, 2 );
9121 free_a_printer(&printer, 2);
9123 return status;
9126 /********************************************************************
9127 * spoolss_enumprinterkey
9128 ********************************************************************/
9131 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9133 fstring key;
9134 fstring *keynames = NULL;
9135 uint16 *enumkeys = NULL;
9136 int num_keys;
9137 int printerkey_len;
9138 POLICY_HND *handle = &q_u->handle;
9139 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9140 NT_PRINTER_DATA *data;
9141 NT_PRINTER_INFO_LEVEL *printer = NULL;
9142 int snum = 0;
9143 WERROR status = WERR_BADFILE;
9146 DEBUG(4,("_spoolss_enumprinterkey\n"));
9148 if (!Printer) {
9149 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9150 return WERR_BADFID;
9153 if ( !get_printer_snum(p,handle, &snum) )
9154 return WERR_BADFID;
9156 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9157 if (!W_ERROR_IS_OK(status))
9158 return status;
9160 /* get the list of subkey names */
9162 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9163 data = &printer->info_2->data;
9165 num_keys = get_printer_subkeys( data, key, &keynames );
9167 if ( num_keys == -1 ) {
9168 status = WERR_BADFILE;
9169 goto done;
9172 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9174 r_u->needed = printerkey_len*2;
9176 if ( q_u->size < r_u->needed ) {
9177 status = WERR_MORE_DATA;
9178 goto done;
9181 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9182 status = WERR_NOMEM;
9183 goto done;
9186 status = WERR_OK;
9188 if ( q_u->size < r_u->needed )
9189 status = WERR_MORE_DATA;
9191 done:
9192 free_a_printer( &printer, 2 );
9193 SAFE_FREE( keynames );
9195 return status;
9198 /********************************************************************
9199 * spoolss_deleteprinterkey
9200 ********************************************************************/
9202 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9204 POLICY_HND *handle = &q_u->handle;
9205 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9206 fstring key;
9207 NT_PRINTER_INFO_LEVEL *printer = NULL;
9208 int snum=0;
9209 WERROR status;
9211 DEBUG(5,("spoolss_deleteprinterkey\n"));
9213 if (!Printer) {
9214 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9215 return WERR_BADFID;
9218 /* if keyname == NULL, return error */
9220 if ( !q_u->keyname.buffer )
9221 return WERR_INVALID_PARAM;
9223 if (!get_printer_snum(p, handle, &snum))
9224 return WERR_BADFID;
9226 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9227 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9228 return WERR_ACCESS_DENIED;
9231 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9232 if (!W_ERROR_IS_OK(status))
9233 return status;
9235 /* delete the key and all subneys */
9237 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9239 status = delete_all_printer_data( printer->info_2, key );
9241 if ( W_ERROR_IS_OK(status) )
9242 status = mod_a_printer(printer, 2);
9244 free_a_printer( &printer, 2 );
9246 return status;
9250 /********************************************************************
9251 * spoolss_enumprinterdataex
9252 ********************************************************************/
9254 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9256 POLICY_HND *handle = &q_u->handle;
9257 uint32 in_size = q_u->size;
9258 uint32 num_entries,
9259 needed;
9260 NT_PRINTER_INFO_LEVEL *printer = NULL;
9261 PRINTER_ENUM_VALUES *enum_values = NULL;
9262 NT_PRINTER_DATA *p_data;
9263 fstring key;
9264 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9265 int snum;
9266 WERROR result;
9267 int key_index;
9268 int i;
9269 REGISTRY_VALUE *val;
9270 char *value_name;
9271 int data_len;
9274 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9276 if (!Printer) {
9277 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9278 return WERR_BADFID;
9282 * first check for a keyname of NULL or "". Win2k seems to send
9283 * this a lot and we should send back WERR_INVALID_PARAM
9284 * no need to spend time looking up the printer in this case.
9285 * --jerry
9288 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9289 if ( !strlen(key) ) {
9290 result = WERR_INVALID_PARAM;
9291 goto done;
9294 /* get the printer off of disk */
9296 if (!get_printer_snum(p,handle, &snum))
9297 return WERR_BADFID;
9299 ZERO_STRUCT(printer);
9300 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9301 if (!W_ERROR_IS_OK(result))
9302 return result;
9304 /* now look for a match on the key name */
9306 p_data = &printer->info_2->data;
9308 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9309 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9311 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9312 result = WERR_INVALID_PARAM;
9313 goto done;
9316 result = WERR_OK;
9317 needed = 0;
9319 /* allocate the memory for the array of pointers -- if necessary */
9321 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9322 if ( num_entries )
9324 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9326 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9327 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9328 result = WERR_NOMEM;
9329 goto done;
9332 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9336 * loop through all params and build the array to pass
9337 * back to the client
9340 for ( i=0; i<num_entries; i++ )
9342 /* lookup the registry value */
9344 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9345 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9347 /* copy the data */
9349 value_name = regval_name( val );
9350 init_unistr( &enum_values[i].valuename, value_name );
9351 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9352 enum_values[i].type = regval_type( val );
9354 data_len = regval_size( val );
9355 if ( data_len ) {
9356 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9358 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9359 data_len ));
9360 result = WERR_NOMEM;
9361 goto done;
9364 enum_values[i].data_len = data_len;
9366 /* keep track of the size of the array in bytes */
9368 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9371 /* housekeeping information in the reply */
9373 r_u->needed = needed;
9374 r_u->returned = num_entries;
9376 if (needed > in_size) {
9377 result = WERR_MORE_DATA;
9378 goto done;
9381 /* copy data into the reply */
9383 r_u->ctr.size = r_u->needed;
9384 r_u->ctr.size_of_array = r_u->returned;
9385 r_u->ctr.values = enum_values;
9389 done:
9390 if ( printer )
9391 free_a_printer(&printer, 2);
9393 return result;
9396 /****************************************************************************
9397 ****************************************************************************/
9399 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9401 init_unistr(&info->name, name);
9404 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9405 UNISTR2 *environment,
9406 RPC_BUFFER *buffer,
9407 uint32 offered,
9408 uint32 *needed)
9410 pstring path;
9411 pstring long_archi;
9412 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9413 WERROR result = WERR_OK;
9415 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9417 if (!get_short_archi(long_archi))
9418 return WERR_INVALID_ENVIRONMENT;
9420 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9421 return WERR_NOMEM;
9423 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9425 fill_printprocessordirectory_1(info, path);
9427 *needed += spoolss_size_printprocessordirectory_info_1(info);
9429 if (*needed > offered) {
9430 result = WERR_INSUFFICIENT_BUFFER;
9431 goto out;
9434 if (!rpcbuf_alloc_size(buffer, *needed)) {
9435 result = WERR_INSUFFICIENT_BUFFER;
9436 goto out;
9439 smb_io_printprocessordirectory_1("", buffer, info, 0);
9441 out:
9442 SAFE_FREE(info);
9444 return result;
9447 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9449 uint32 level = q_u->level;
9450 RPC_BUFFER *buffer = NULL;
9451 uint32 offered = q_u->offered;
9452 uint32 *needed = &r_u->needed;
9453 WERROR result;
9455 /* that's an [in out] buffer */
9457 if ( q_u->buffer ) {
9458 rpcbuf_move(q_u->buffer, &r_u->buffer);
9459 buffer = r_u->buffer;
9462 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9464 *needed=0;
9466 switch(level) {
9467 case 1:
9468 result = getprintprocessordirectory_level_1
9469 (&q_u->name, &q_u->environment, buffer, offered, needed);
9470 break;
9471 default:
9472 result = WERR_UNKNOWN_LEVEL;
9475 return result;
9478 #if 0
9480 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9481 SPOOL_R_REPLYOPENPRINTER *r_u)
9483 DEBUG(5,("_spoolss_replyopenprinter\n"));
9485 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9487 return WERR_OK;
9490 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9491 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9493 DEBUG(5,("_spoolss_replycloseprinter\n"));
9494 return WERR_OK;
9497 #endif