TEMP: Rollup of lots of changes so they don't get lost
[Samba/vfs_proxy.git] / source3 / rpc_server / srv_spoolss_nt.c
blob744de67db428c157f3a7db477c1f7e50ba492e3b
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 3 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, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
28 #include "includes.h"
30 extern userdom_struct current_user_info;
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 struct table_node {
43 const char *long_archi;
44 const char *short_archi;
45 int version;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
54 int snum;
55 uint32 counter;
56 } counter_printer_0;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
71 const char *name;
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
75 /********************************************************************
76 * Canonicalize servername.
77 ********************************************************************/
79 static const char *canon_servername(const char *servername)
81 const char *pservername = servername;
82 while (*pservername == '\\') {
83 pservername++;
85 return pservername;
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
91 switch (v) {
92 case LPQ_QUEUED:
93 return 0;
94 case LPQ_PAUSED:
95 return JOB_STATUS_PAUSED;
96 case LPQ_SPOOLING:
97 return JOB_STATUS_SPOOLING;
98 case LPQ_PRINTING:
99 return JOB_STATUS_PRINTING;
100 case LPQ_ERROR:
101 return JOB_STATUS_ERROR;
102 case LPQ_DELETING:
103 return JOB_STATUS_DELETING;
104 case LPQ_OFFLINE:
105 return JOB_STATUS_OFFLINE;
106 case LPQ_PAPEROUT:
107 return JOB_STATUS_PAPEROUT;
108 case LPQ_PRINTED:
109 return JOB_STATUS_PRINTED;
110 case LPQ_DELETED:
111 return JOB_STATUS_DELETED;
112 case LPQ_BLOCKED:
113 return JOB_STATUS_BLOCKED;
114 case LPQ_USER_INTERVENTION:
115 return JOB_STATUS_USER_INTERVENTION;
117 return 0;
120 static int nt_printq_status(int v)
122 switch (v) {
123 case LPQ_PAUSED:
124 return PRINTER_STATUS_PAUSED;
125 case LPQ_QUEUED:
126 case LPQ_SPOOLING:
127 case LPQ_PRINTING:
128 return 0;
130 return 0;
133 /****************************************************************************
134 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
135 ****************************************************************************/
137 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
139 if (*pp == NULL)
140 return;
142 SAFE_FREE((*pp)->ctr.type);
143 SAFE_FREE(*pp);
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
152 WERROR result;
155 * Tell the specific printing tdb we no longer want messages for this printer
156 * by deregistering our PID.
159 if (!print_notify_deregister_pid(snum))
160 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
162 /* weird if the test succeds !!! */
163 if (smb_connections==0) {
164 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
165 return;
168 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe,
169 talloc_tos(),
170 handle);
172 if (!W_ERROR_IS_OK(result))
173 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174 win_errstr(result)));
176 /* if it's the last connection, deconnect the IPC$ share */
177 if (smb_connections==1) {
179 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
182 messaging_deregister(smbd_messaging_context(),
183 MSG_PRINTER_NOTIFY2, NULL);
185 /* Tell the connections db we're no longer interested in
186 * printer notify messages. */
188 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
191 smb_connections--;
194 /****************************************************************************
195 Functions to free a printer entry datastruct.
196 ****************************************************************************/
198 static void free_printer_entry(void *ptr)
200 Printer_entry *Printer = (Printer_entry *)ptr;
202 if (Printer->notify.client_connected==True) {
203 int snum = -1;
205 if ( Printer->printer_type == SPLHND_SERVER) {
206 snum = -1;
207 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
208 } else if (Printer->printer_type == SPLHND_PRINTER) {
209 snum = print_queue_snum(Printer->sharename);
210 if (snum != -1)
211 srv_spoolss_replycloseprinter(snum,
212 &Printer->notify.client_hnd);
216 Printer->notify.flags=0;
217 Printer->notify.options=0;
218 Printer->notify.localmachine[0]='\0';
219 Printer->notify.printerlocal=0;
220 free_spool_notify_option(&Printer->notify.option);
221 Printer->notify.option=NULL;
222 Printer->notify.client_connected=False;
224 free_nt_devicemode( &Printer->nt_devmode );
225 free_a_printer( &Printer->printer_info, 2 );
227 talloc_destroy( Printer->ctx );
229 /* Remove from the internal list. */
230 DLIST_REMOVE(printers_list, Printer);
232 SAFE_FREE(Printer);
235 /****************************************************************************
236 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
237 ****************************************************************************/
239 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
241 SPOOL_NOTIFY_OPTION *new_sp = NULL;
243 if (!sp)
244 return NULL;
246 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
247 if (!new_sp)
248 return NULL;
250 *new_sp = *sp;
252 if (sp->ctr.count) {
253 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
255 if (!new_sp->ctr.type) {
256 SAFE_FREE(new_sp);
257 return NULL;
261 return new_sp;
264 /****************************************************************************
265 find printer index by handle
266 ****************************************************************************/
268 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
270 Printer_entry *find_printer = NULL;
272 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
273 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
274 return NULL;
277 return find_printer;
280 /****************************************************************************
281 Close printer index by handle.
282 ****************************************************************************/
284 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
286 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
288 if (!Printer) {
289 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
290 return False;
293 close_policy_hnd(p, hnd);
295 return True;
298 /****************************************************************************
299 Delete a printer given a handle.
300 ****************************************************************************/
302 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
304 char *cmd = lp_deleteprinter_cmd();
305 char *command = NULL;
306 int ret;
307 SE_PRIV se_printop = SE_PRINT_OPERATOR;
308 bool is_print_op = False;
310 /* can't fail if we don't try */
312 if ( !*cmd )
313 return WERR_OK;
315 command = talloc_asprintf(ctx,
316 "%s \"%s\"",
317 cmd, sharename);
318 if (!command) {
319 return WERR_NOMEM;
321 if ( token )
322 is_print_op = user_has_privileges( token, &se_printop );
324 DEBUG(10,("Running [%s]\n", command));
326 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
328 if ( is_print_op )
329 become_root();
331 if ( (ret = smbrun(command, NULL)) == 0 ) {
332 /* Tell everyone we updated smb.conf. */
333 message_send_all(smbd_messaging_context(),
334 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
337 if ( is_print_op )
338 unbecome_root();
340 /********** END SePrintOperatorPrivlege BLOCK **********/
342 DEBUGADD(10,("returned [%d]\n", ret));
344 TALLOC_FREE(command);
346 if (ret != 0)
347 return WERR_BADFID; /* What to return here? */
349 /* go ahead and re-read the services immediately */
350 reload_services( False );
352 if ( lp_servicenumber( sharename ) < 0 )
353 return WERR_ACCESS_DENIED;
355 return WERR_OK;
358 /****************************************************************************
359 Delete a printer given a handle.
360 ****************************************************************************/
362 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
364 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
366 if (!Printer) {
367 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
368 return WERR_BADFID;
372 * It turns out that Windows allows delete printer on a handle
373 * opened by an admin user, then used on a pipe handle created
374 * by an anonymous user..... but they're working on security.... riiight !
375 * JRA.
378 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
379 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
380 return WERR_ACCESS_DENIED;
383 /* this does not need a become root since the access check has been
384 done on the handle already */
386 if (del_a_printer( Printer->sharename ) != 0) {
387 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
388 return WERR_BADFID;
391 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
392 Printer->sharename );
395 /****************************************************************************
396 Return the snum of a printer corresponding to an handle.
397 ****************************************************************************/
399 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
400 struct share_params **params)
402 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
404 if (!Printer) {
405 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
406 return False;
409 switch (Printer->printer_type) {
410 case SPLHND_PRINTER:
411 DEBUG(4,("short name:%s\n", Printer->sharename));
412 *number = print_queue_snum(Printer->sharename);
413 return (*number != -1);
414 case SPLHND_SERVER:
415 return False;
416 default:
417 return False;
421 /****************************************************************************
422 Set printer handle type.
423 Check if it's \\server or \\server\printer
424 ****************************************************************************/
426 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
428 DEBUG(3,("Setting printer type=%s\n", handlename));
430 if ( strlen(handlename) < 3 ) {
431 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
432 return False;
435 /* it's a print server */
436 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
437 DEBUGADD(4,("Printer is a print server\n"));
438 Printer->printer_type = SPLHND_SERVER;
440 /* it's a printer (set_printer_hnd_name() will handle port monitors */
441 else {
442 DEBUGADD(4,("Printer is a printer\n"));
443 Printer->printer_type = SPLHND_PRINTER;
446 return True;
449 /****************************************************************************
450 Set printer handle name.. Accept names like \\server, \\server\printer,
451 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
452 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
453 XcvDataPort() interface.
454 ****************************************************************************/
456 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
458 int snum;
459 int n_services=lp_numservices();
460 char *aprinter, *printername;
461 const char *servername;
462 fstring sname;
463 bool found=False;
464 NT_PRINTER_INFO_LEVEL *printer = NULL;
465 WERROR result;
467 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
469 aprinter = handlename;
470 if ( *handlename == '\\' ) {
471 servername = canon_servername(handlename);
472 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
473 *aprinter = '\0';
474 aprinter++;
476 } else {
477 servername = "";
480 /* save the servername to fill in replies on this handle */
482 if ( !is_myname_or_ipaddr( servername ) )
483 return False;
485 fstrcpy( Printer->servername, servername );
487 if ( Printer->printer_type == SPLHND_SERVER )
488 return True;
490 if ( Printer->printer_type != SPLHND_PRINTER )
491 return False;
493 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
495 /* check for the Port Monitor Interface */
497 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
498 Printer->printer_type = SPLHND_PORTMON_TCP;
499 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
500 found = True;
502 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
503 Printer->printer_type = SPLHND_PORTMON_LOCAL;
504 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
505 found = True;
508 /* Search all sharenames first as this is easier than pulling
509 the printer_info_2 off of disk. Don't use find_service() since
510 that calls out to map_username() */
512 /* do another loop to look for printernames */
514 for (snum=0; !found && snum<n_services; snum++) {
516 /* no point going on if this is not a printer */
518 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
519 continue;
521 fstrcpy(sname, lp_servicename(snum));
522 if ( strequal( aprinter, sname ) ) {
523 found = True;
524 break;
527 /* no point looking up the printer object if
528 we aren't allowing printername != sharename */
530 if ( lp_force_printername(snum) )
531 continue;
533 fstrcpy(sname, lp_servicename(snum));
535 printer = NULL;
537 /* This call doesn't fill in the location or comment from
538 * a CUPS server for efficiency with large numbers of printers.
539 * JRA.
542 result = get_a_printer_search( NULL, &printer, 2, sname );
543 if ( !W_ERROR_IS_OK(result) ) {
544 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
545 sname, win_errstr(result)));
546 continue;
549 /* printername is always returned as \\server\printername */
550 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
551 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
552 printer->info_2->printername));
553 free_a_printer( &printer, 2);
554 continue;
557 printername++;
559 if ( strequal(printername, aprinter) ) {
560 free_a_printer( &printer, 2);
561 found = True;
562 break;
565 DEBUGADD(10, ("printername: %s\n", printername));
567 free_a_printer( &printer, 2);
570 free_a_printer( &printer, 2);
572 if ( !found ) {
573 DEBUGADD(4,("Printer not found\n"));
574 return False;
577 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
579 fstrcpy(Printer->sharename, sname);
581 return True;
584 /****************************************************************************
585 Find first available printer slot. creates a printer handle for you.
586 ****************************************************************************/
588 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
590 Printer_entry *new_printer;
592 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
594 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
595 return False;
597 ZERO_STRUCTP(new_printer);
599 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
600 SAFE_FREE(new_printer);
601 return False;
604 /* Add to the internal list. */
605 DLIST_ADD(printers_list, new_printer);
607 new_printer->notify.option=NULL;
609 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
610 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
611 close_printer_handle(p, hnd);
612 return False;
615 if (!set_printer_hnd_printertype(new_printer, name)) {
616 close_printer_handle(p, hnd);
617 return False;
620 if (!set_printer_hnd_name(new_printer, name)) {
621 close_printer_handle(p, hnd);
622 return False;
625 new_printer->access_granted = access_granted;
627 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
629 return True;
632 /***************************************************************************
633 check to see if the client motify handle is monitoring the notification
634 given by (notify_type, notify_field).
635 **************************************************************************/
637 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
638 uint16 notify_field)
640 return True;
643 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
644 uint16 notify_field)
646 SPOOL_NOTIFY_OPTION *option = p->notify.option;
647 uint32 i, j;
650 * Flags should always be zero when the change notify
651 * is registered by the client's spooler. A user Win32 app
652 * might use the flags though instead of the NOTIFY_OPTION_INFO
653 * --jerry
656 if (!option) {
657 return False;
660 if (p->notify.flags)
661 return is_monitoring_event_flags(
662 p->notify.flags, notify_type, notify_field);
664 for (i = 0; i < option->count; i++) {
666 /* Check match for notify_type */
668 if (option->ctr.type[i].type != notify_type)
669 continue;
671 /* Check match for field */
673 for (j = 0; j < option->ctr.type[i].count; j++) {
674 if (option->ctr.type[i].fields[j] == notify_field) {
675 return True;
680 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
681 p->servername, p->sharename, notify_type, notify_field));
683 return False;
686 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
688 static void notify_one_value(struct spoolss_notify_msg *msg,
689 SPOOL_NOTIFY_INFO_DATA *data,
690 TALLOC_CTX *mem_ctx)
692 data->notify_data.value[0] = msg->notify.value[0];
693 data->notify_data.value[1] = 0;
696 static void notify_string(struct spoolss_notify_msg *msg,
697 SPOOL_NOTIFY_INFO_DATA *data,
698 TALLOC_CTX *mem_ctx)
700 UNISTR2 unistr;
702 /* The length of the message includes the trailing \0 */
704 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
706 data->notify_data.data.length = msg->len * 2;
707 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
709 if (!data->notify_data.data.string) {
710 data->notify_data.data.length = 0;
711 return;
714 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
717 static void notify_system_time(struct spoolss_notify_msg *msg,
718 SPOOL_NOTIFY_INFO_DATA *data,
719 TALLOC_CTX *mem_ctx)
721 SYSTEMTIME systime;
722 prs_struct ps;
724 if (msg->len != sizeof(time_t)) {
725 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
726 msg->len));
727 return;
730 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
731 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
732 return;
735 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
736 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
737 prs_mem_free(&ps);
738 return;
741 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
742 prs_mem_free(&ps);
743 return;
746 data->notify_data.data.length = prs_offset(&ps);
747 if (prs_offset(&ps)) {
748 data->notify_data.data.string = (uint16 *)
749 TALLOC(mem_ctx, prs_offset(&ps));
750 if (!data->notify_data.data.string) {
751 prs_mem_free(&ps);
752 return;
754 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
755 } else {
756 data->notify_data.data.string = NULL;
759 prs_mem_free(&ps);
762 struct notify2_message_table {
763 const char *name;
764 void (*fn)(struct spoolss_notify_msg *msg,
765 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
768 static struct notify2_message_table printer_notify_table[] = {
769 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
770 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
771 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
772 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
773 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
774 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
775 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
776 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
777 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
778 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
779 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
780 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
781 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
782 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
783 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
784 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
785 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
786 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
787 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
790 static struct notify2_message_table job_notify_table[] = {
791 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
792 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
793 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
794 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
795 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
796 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
797 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
798 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
799 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
800 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
801 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
802 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
803 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
804 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
805 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
806 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
807 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
808 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
809 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
810 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
811 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
812 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
813 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
814 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
818 /***********************************************************************
819 Allocate talloc context for container object
820 **********************************************************************/
822 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
824 if ( !ctr )
825 return;
827 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
829 return;
832 /***********************************************************************
833 release all allocated memory and zero out structure
834 **********************************************************************/
836 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
838 if ( !ctr )
839 return;
841 if ( ctr->ctx )
842 talloc_destroy(ctr->ctx);
844 ZERO_STRUCTP(ctr);
846 return;
849 /***********************************************************************
850 **********************************************************************/
852 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
854 if ( !ctr )
855 return NULL;
857 return ctr->ctx;
860 /***********************************************************************
861 **********************************************************************/
863 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
865 if ( !ctr || !ctr->msg_groups )
866 return NULL;
868 if ( idx >= ctr->num_groups )
869 return NULL;
871 return &ctr->msg_groups[idx];
875 /***********************************************************************
876 How many groups of change messages do we have ?
877 **********************************************************************/
879 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
881 if ( !ctr )
882 return 0;
884 return ctr->num_groups;
887 /***********************************************************************
888 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
889 **********************************************************************/
891 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
893 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
894 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
895 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
896 int i, new_slot;
898 if ( !ctr || !msg )
899 return 0;
901 /* loop over all groups looking for a matching printer name */
903 for ( i=0; i<ctr->num_groups; i++ ) {
904 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
905 break;
908 /* add a new group? */
910 if ( i == ctr->num_groups ) {
911 ctr->num_groups++;
913 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
914 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
915 return 0;
917 ctr->msg_groups = groups;
919 /* clear the new entry and set the printer name */
921 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
922 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
925 /* add the change messages; 'i' is the correct index now regardless */
927 msg_grp = &ctr->msg_groups[i];
929 msg_grp->num_msgs++;
931 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
932 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
933 return 0;
935 msg_grp->msgs = msg_list;
937 new_slot = msg_grp->num_msgs-1;
938 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
940 /* need to allocate own copy of data */
942 if ( msg->len != 0 )
943 msg_grp->msgs[new_slot].notify.data = (char *)
944 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
946 return ctr->num_groups;
949 /***********************************************************************
950 Send a change notication message on all handles which have a call
951 back registered
952 **********************************************************************/
954 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
956 Printer_entry *p;
957 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
958 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
959 SPOOLSS_NOTIFY_MSG *messages;
960 int sending_msg_count;
962 if ( !msg_group ) {
963 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
964 return;
967 messages = msg_group->msgs;
969 if ( !messages ) {
970 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
971 return;
974 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
976 /* loop over all printers */
978 for (p = printers_list; p; p = p->next) {
979 SPOOL_NOTIFY_INFO_DATA *data;
980 uint32 data_len = 0;
981 uint32 id;
982 int i;
984 /* Is there notification on this handle? */
986 if ( !p->notify.client_connected )
987 continue;
989 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
991 /* For this printer? Print servers always receive
992 notifications. */
994 if ( ( p->printer_type == SPLHND_PRINTER ) &&
995 ( !strequal(msg_group->printername, p->sharename) ) )
996 continue;
998 DEBUG(10,("Our printer\n"));
1000 /* allocate the max entries possible */
1002 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1003 if (!data) {
1004 return;
1007 ZERO_STRUCTP(data);
1009 /* build the array of change notifications */
1011 sending_msg_count = 0;
1013 for ( i=0; i<msg_group->num_msgs; i++ ) {
1014 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1016 /* Are we monitoring this event? */
1018 if (!is_monitoring_event(p, msg->type, msg->field))
1019 continue;
1021 sending_msg_count++;
1024 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1025 msg->type, msg->field, p->sharename));
1028 * if the is a printer notification handle and not a job notification
1029 * type, then set the id to 0. Other wise just use what was specified
1030 * in the message.
1032 * When registering change notification on a print server handle
1033 * we always need to send back the id (snum) matching the printer
1034 * for which the change took place. For change notify registered
1035 * on a printer handle, this does not matter and the id should be 0.
1037 * --jerry
1040 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1041 id = 0;
1042 else
1043 id = msg->id;
1046 /* Convert unix jobid to smb jobid */
1048 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1049 id = sysjob_to_jobid(msg->id);
1051 if (id == -1) {
1052 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1053 goto done;
1057 construct_info_data( &data[data_len], msg->type, msg->field, id );
1059 switch(msg->type) {
1060 case PRINTER_NOTIFY_TYPE:
1061 if ( printer_notify_table[msg->field].fn )
1062 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1063 break;
1065 case JOB_NOTIFY_TYPE:
1066 if ( job_notify_table[msg->field].fn )
1067 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1068 break;
1070 default:
1071 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1072 goto done;
1075 data_len++;
1078 if ( sending_msg_count ) {
1079 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1080 data_len, data, p->notify.change, 0 );
1084 done:
1085 DEBUG(8,("send_notify2_changes: Exit...\n"));
1086 return;
1089 /***********************************************************************
1090 **********************************************************************/
1092 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1095 uint32 tv_sec, tv_usec;
1096 size_t offset = 0;
1098 /* Unpack message */
1100 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1101 msg->printer);
1103 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1104 &tv_sec, &tv_usec,
1105 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1107 if (msg->len == 0)
1108 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1109 &msg->notify.value[0], &msg->notify.value[1]);
1110 else
1111 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1112 &msg->len, &msg->notify.data);
1114 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1115 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1117 tv->tv_sec = tv_sec;
1118 tv->tv_usec = tv_usec;
1120 if (msg->len == 0)
1121 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1122 msg->notify.value[1]));
1123 else
1124 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1126 return True;
1129 /********************************************************************
1130 Receive a notify2 message list
1131 ********************************************************************/
1133 static void receive_notify2_message_list(struct messaging_context *msg,
1134 void *private_data,
1135 uint32_t msg_type,
1136 struct server_id server_id,
1137 DATA_BLOB *data)
1139 size_t msg_count, i;
1140 char *buf = (char *)data->data;
1141 char *msg_ptr;
1142 size_t msg_len;
1143 SPOOLSS_NOTIFY_MSG notify;
1144 SPOOLSS_NOTIFY_MSG_CTR messages;
1145 int num_groups;
1147 if (data->length < 4) {
1148 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1149 return;
1152 msg_count = IVAL(buf, 0);
1153 msg_ptr = buf + 4;
1155 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1157 if (msg_count == 0) {
1158 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1159 return;
1162 /* initialize the container */
1164 ZERO_STRUCT( messages );
1165 notify_msg_ctr_init( &messages );
1168 * build message groups for each printer identified
1169 * in a change_notify msg. Remember that a PCN message
1170 * includes the handle returned for the srv_spoolss_replyopenprinter()
1171 * call. Therefore messages are grouped according to printer handle.
1174 for ( i=0; i<msg_count; i++ ) {
1175 struct timeval msg_tv;
1177 if (msg_ptr + 4 - buf > data->length) {
1178 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1179 return;
1182 msg_len = IVAL(msg_ptr,0);
1183 msg_ptr += 4;
1185 if (msg_ptr + msg_len - buf > data->length) {
1186 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1187 return;
1190 /* unpack messages */
1192 ZERO_STRUCT( notify );
1193 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1194 msg_ptr += msg_len;
1196 /* add to correct list in container */
1198 notify_msg_ctr_addmsg( &messages, &notify );
1200 /* free memory that might have been allocated by notify2_unpack_msg() */
1202 if ( notify.len != 0 )
1203 SAFE_FREE( notify.notify.data );
1206 /* process each group of messages */
1208 num_groups = notify_msg_ctr_numgroups( &messages );
1209 for ( i=0; i<num_groups; i++ )
1210 send_notify2_changes( &messages, i );
1213 /* cleanup */
1215 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1217 notify_msg_ctr_destroy( &messages );
1219 return;
1222 /********************************************************************
1223 Send a message to ourself about new driver being installed
1224 so we can upgrade the information for each printer bound to this
1225 driver
1226 ********************************************************************/
1228 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1230 int len = strlen(drivername);
1232 if (!len)
1233 return False;
1235 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1236 drivername));
1238 messaging_send_buf(smbd_messaging_context(), procid_self(),
1239 MSG_PRINTER_DRVUPGRADE,
1240 (uint8 *)drivername, len+1);
1242 return True;
1245 /**********************************************************************
1246 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1247 over all printers, upgrading ones as necessary
1248 **********************************************************************/
1250 void do_drv_upgrade_printer(struct messaging_context *msg,
1251 void *private_data,
1252 uint32_t msg_type,
1253 struct server_id server_id,
1254 DATA_BLOB *data)
1256 fstring drivername;
1257 int snum;
1258 int n_services = lp_numservices();
1259 size_t len;
1261 len = MIN(data->length,sizeof(drivername)-1);
1262 strncpy(drivername, (const char *)data->data, len);
1264 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1266 /* Iterate the printer list */
1268 for (snum=0; snum<n_services; snum++)
1270 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1272 WERROR result;
1273 NT_PRINTER_INFO_LEVEL *printer = NULL;
1275 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1276 if (!W_ERROR_IS_OK(result))
1277 continue;
1279 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1281 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1283 /* all we care about currently is the change_id */
1285 result = mod_a_printer(printer, 2);
1286 if (!W_ERROR_IS_OK(result)) {
1287 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1288 win_errstr(result)));
1292 free_a_printer(&printer, 2);
1296 /* all done */
1299 /********************************************************************
1300 Update the cache for all printq's with a registered client
1301 connection
1302 ********************************************************************/
1304 void update_monitored_printq_cache( void )
1306 Printer_entry *printer = printers_list;
1307 int snum;
1309 /* loop through all printers and update the cache where
1310 client_connected == True */
1311 while ( printer )
1313 if ( (printer->printer_type == SPLHND_PRINTER)
1314 && printer->notify.client_connected )
1316 snum = print_queue_snum(printer->sharename);
1317 print_queue_status( snum, NULL, NULL );
1320 printer = printer->next;
1323 return;
1325 /********************************************************************
1326 Send a message to ourself about new driver being installed
1327 so we can upgrade the information for each printer bound to this
1328 driver
1329 ********************************************************************/
1331 static bool srv_spoolss_reset_printerdata(char* drivername)
1333 int len = strlen(drivername);
1335 if (!len)
1336 return False;
1338 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1339 drivername));
1341 messaging_send_buf(smbd_messaging_context(), procid_self(),
1342 MSG_PRINTERDATA_INIT_RESET,
1343 (uint8 *)drivername, len+1);
1345 return True;
1348 /**********************************************************************
1349 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1350 over all printers, resetting printer data as neessary
1351 **********************************************************************/
1353 void reset_all_printerdata(struct messaging_context *msg,
1354 void *private_data,
1355 uint32_t msg_type,
1356 struct server_id server_id,
1357 DATA_BLOB *data)
1359 fstring drivername;
1360 int snum;
1361 int n_services = lp_numservices();
1362 size_t len;
1364 len = MIN( data->length, sizeof(drivername)-1 );
1365 strncpy( drivername, (const char *)data->data, len );
1367 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1369 /* Iterate the printer list */
1371 for ( snum=0; snum<n_services; snum++ )
1373 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1375 WERROR result;
1376 NT_PRINTER_INFO_LEVEL *printer = NULL;
1378 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1379 if ( !W_ERROR_IS_OK(result) )
1380 continue;
1383 * if the printer is bound to the driver,
1384 * then reset to the new driver initdata
1387 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1389 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1391 if ( !set_driver_init(printer, 2) ) {
1392 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1393 printer->info_2->printername, printer->info_2->drivername));
1396 result = mod_a_printer( printer, 2 );
1397 if ( !W_ERROR_IS_OK(result) ) {
1398 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1399 get_dos_error_msg(result)));
1403 free_a_printer( &printer, 2 );
1407 /* all done */
1409 return;
1412 /********************************************************************
1413 Copy routines used by convert_to_openprinterex()
1414 *******************************************************************/
1416 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1418 DEVICEMODE *d;
1419 int len;
1421 if (!devmode)
1422 return NULL;
1424 DEBUG (8,("dup_devmode\n"));
1426 /* bulk copy first */
1428 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1429 if (!d)
1430 return NULL;
1432 /* dup the pointer members separately */
1434 len = unistrlen(devmode->devicename.buffer);
1435 if (len != -1) {
1436 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1437 if (!d->devicename.buffer) {
1438 return NULL;
1440 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1441 return NULL;
1445 len = unistrlen(devmode->formname.buffer);
1446 if (len != -1) {
1447 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1448 if (!d->formname.buffer) {
1449 return NULL;
1451 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1452 return NULL;
1455 if (devmode->driverextra) {
1456 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1457 devmode->driverextra);
1458 if (!d->dev_private) {
1459 return NULL;
1461 } else {
1462 d->dev_private = NULL;
1464 return d;
1467 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1469 if (!new_ctr || !ctr)
1470 return;
1472 DEBUG(8,("copy_devmode_ctr\n"));
1474 new_ctr->size = ctr->size;
1475 new_ctr->devmode_ptr = ctr->devmode_ptr;
1477 if(ctr->devmode_ptr)
1478 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1481 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1483 if (!new_def || !def)
1484 return;
1486 DEBUG(8,("copy_printer_defaults\n"));
1488 new_def->datatype_ptr = def->datatype_ptr;
1490 if (def->datatype_ptr)
1491 copy_unistr2(&new_def->datatype, &def->datatype);
1493 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1495 new_def->access_required = def->access_required;
1498 /********************************************************************
1499 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1500 * SPOOL_Q_OPEN_PRINTER_EX structure
1501 ********************************************************************/
1503 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1505 if (!q_u_ex || !q_u)
1506 return WERR_OK;
1508 DEBUG(8,("convert_to_openprinterex\n"));
1510 if ( q_u->printername ) {
1511 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1512 if (q_u_ex->printername == NULL)
1513 return WERR_NOMEM;
1514 copy_unistr2(q_u_ex->printername, q_u->printername);
1517 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1519 return WERR_OK;
1522 /********************************************************************
1523 * spoolss_open_printer
1525 * called from the spoolss dispatcher
1526 ********************************************************************/
1528 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1530 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1531 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1533 if (!q_u || !r_u)
1534 return WERR_NOMEM;
1536 ZERO_STRUCT(q_u_ex);
1537 ZERO_STRUCT(r_u_ex);
1539 /* convert the OpenPrinter() call to OpenPrinterEx() */
1541 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1542 if (!W_ERROR_IS_OK(r_u_ex.status))
1543 return r_u_ex.status;
1545 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1547 /* convert back to OpenPrinter() */
1549 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1551 if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
1552 /* OpenPrinterEx returns this for a bad
1553 * printer name. We must return WERR_INVALID_PRINTER_NAME
1554 * instead.
1556 r_u->status = WERR_INVALID_PRINTER_NAME;
1558 return r_u->status;
1561 /********************************************************************
1562 ********************************************************************/
1564 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1566 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1567 POLICY_HND *handle = &r_u->handle;
1569 fstring name;
1570 int snum;
1571 Printer_entry *Printer=NULL;
1573 if (!q_u->printername) {
1574 return WERR_INVALID_PARAM;
1577 /* some sanity check because you can open a printer or a print server */
1578 /* aka: \\server\printer or \\server */
1580 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1582 DEBUGADD(3,("checking name: %s\n",name));
1584 if (!open_printer_hnd(p, handle, name, 0)) {
1585 return WERR_INVALID_PARAM;
1588 Printer=find_printer_index_by_hnd(p, handle);
1589 if ( !Printer ) {
1590 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1591 "handle we created for printer %s\n", name ));
1592 close_printer_handle(p,handle);
1593 return WERR_INVALID_PARAM;
1597 * First case: the user is opening the print server:
1599 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1600 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1602 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1603 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1604 * or if the user is listed in the smb.conf printer admin parameter.
1606 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1607 * client view printer folder, but does not show the MSAPW.
1609 * Note: this test needs code to check access rights here too. Jeremy
1610 * could you look at this?
1612 * Second case: the user is opening a printer:
1613 * NT doesn't let us connect to a printer if the connecting user
1614 * doesn't have print permission.
1616 * Third case: user is opening a Port Monitor
1617 * access checks same as opening a handle to the print server.
1620 switch (Printer->printer_type )
1622 case SPLHND_SERVER:
1623 case SPLHND_PORTMON_TCP:
1624 case SPLHND_PORTMON_LOCAL:
1625 /* Printserver handles use global struct... */
1627 snum = -1;
1629 /* Map standard access rights to object specific access rights */
1631 se_map_standard(&printer_default->access_required,
1632 &printserver_std_mapping);
1634 /* Deny any object specific bits that don't apply to print
1635 servers (i.e printer and job specific bits) */
1637 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1639 if (printer_default->access_required &
1640 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1641 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1642 close_printer_handle(p, handle);
1643 return WERR_ACCESS_DENIED;
1646 /* Allow admin access */
1648 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1650 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1652 if (!lp_ms_add_printer_wizard()) {
1653 close_printer_handle(p, handle);
1654 return WERR_ACCESS_DENIED;
1657 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1658 and not a printer admin, then fail */
1660 if ((p->server_info->utok.uid != 0) &&
1661 !user_has_privileges(p->server_info->ptok,
1662 &se_printop ) &&
1663 !token_contains_name_in_list(
1664 uidtoname(p->server_info->utok.uid),
1665 NULL, NULL,
1666 p->server_info->ptok,
1667 lp_printer_admin(snum))) {
1668 close_printer_handle(p, handle);
1669 return WERR_ACCESS_DENIED;
1672 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1674 else
1676 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1679 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1680 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1682 /* We fall through to return WERR_OK */
1683 break;
1685 case SPLHND_PRINTER:
1686 /* NT doesn't let us connect to a printer if the connecting user
1687 doesn't have print permission. */
1689 if (!get_printer_snum(p, handle, &snum, NULL)) {
1690 close_printer_handle(p, handle);
1691 return WERR_BADFID;
1694 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1696 /* map an empty access mask to the minimum access mask */
1697 if (printer_default->access_required == 0x0)
1698 printer_default->access_required = PRINTER_ACCESS_USE;
1701 * If we are not serving the printer driver for this printer,
1702 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1703 * will keep NT clients happy --jerry
1706 if (lp_use_client_driver(snum)
1707 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1709 printer_default->access_required = PRINTER_ACCESS_USE;
1712 /* check smb.conf parameters and the the sec_desc */
1714 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1715 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1716 return WERR_ACCESS_DENIED;
1719 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1720 p->server_info->ptok, snum) ||
1721 !print_access_check(p->server_info, snum,
1722 printer_default->access_required)) {
1723 DEBUG(3, ("access DENIED for printer open\n"));
1724 close_printer_handle(p, handle);
1725 return WERR_ACCESS_DENIED;
1728 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1729 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1730 close_printer_handle(p, handle);
1731 return WERR_ACCESS_DENIED;
1734 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1735 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1736 else
1737 printer_default->access_required = PRINTER_ACCESS_USE;
1739 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1740 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1742 break;
1744 default:
1745 /* sanity check to prevent programmer error */
1746 return WERR_BADFID;
1749 Printer->access_granted = printer_default->access_required;
1752 * If the client sent a devmode in the OpenPrinter() call, then
1753 * save it here in case we get a job submission on this handle
1756 if ( (Printer->printer_type != SPLHND_SERVER)
1757 && q_u->printer_default.devmode_cont.devmode_ptr )
1759 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1760 &Printer->nt_devmode );
1763 #if 0 /* JERRY -- I'm doubtful this is really effective */
1764 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1765 optimization in Windows 2000 clients --jerry */
1767 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1768 && (RA_WIN2K == get_remote_arch()) )
1770 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1771 sys_usleep( 500000 );
1773 #endif
1775 return WERR_OK;
1778 /****************************************************************************
1779 ****************************************************************************/
1781 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1782 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1784 bool ret;
1786 switch (level) {
1787 case 2:
1788 /* allocate memory if needed. Messy because
1789 convert_printer_info is used to update an existing
1790 printer or build a new one */
1792 if ( !printer->info_2 ) {
1793 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1794 if ( !printer->info_2 ) {
1795 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1796 return False;
1800 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1801 printer->info_2->setuptime = time(NULL);
1803 return ret;
1806 return False;
1809 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1810 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1812 bool result = True;
1814 switch (level) {
1815 case 3:
1816 printer->info_3=NULL;
1817 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1818 result = False;
1819 break;
1820 case 6:
1821 printer->info_6=NULL;
1822 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1823 result = False;
1824 break;
1825 default:
1826 break;
1829 return result;
1832 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1833 NT_DEVICEMODE **pp_nt_devmode)
1835 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1838 * Ensure nt_devmode is a valid pointer
1839 * as we will be overwriting it.
1842 if (nt_devmode == NULL) {
1843 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1844 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1845 return False;
1848 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1849 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1851 nt_devmode->specversion=devmode->specversion;
1852 nt_devmode->driverversion=devmode->driverversion;
1853 nt_devmode->size=devmode->size;
1854 nt_devmode->fields=devmode->fields;
1855 nt_devmode->orientation=devmode->orientation;
1856 nt_devmode->papersize=devmode->papersize;
1857 nt_devmode->paperlength=devmode->paperlength;
1858 nt_devmode->paperwidth=devmode->paperwidth;
1859 nt_devmode->scale=devmode->scale;
1860 nt_devmode->copies=devmode->copies;
1861 nt_devmode->defaultsource=devmode->defaultsource;
1862 nt_devmode->printquality=devmode->printquality;
1863 nt_devmode->color=devmode->color;
1864 nt_devmode->duplex=devmode->duplex;
1865 nt_devmode->yresolution=devmode->yresolution;
1866 nt_devmode->ttoption=devmode->ttoption;
1867 nt_devmode->collate=devmode->collate;
1869 nt_devmode->logpixels=devmode->logpixels;
1870 nt_devmode->bitsperpel=devmode->bitsperpel;
1871 nt_devmode->pelswidth=devmode->pelswidth;
1872 nt_devmode->pelsheight=devmode->pelsheight;
1873 nt_devmode->displayflags=devmode->displayflags;
1874 nt_devmode->displayfrequency=devmode->displayfrequency;
1875 nt_devmode->icmmethod=devmode->icmmethod;
1876 nt_devmode->icmintent=devmode->icmintent;
1877 nt_devmode->mediatype=devmode->mediatype;
1878 nt_devmode->dithertype=devmode->dithertype;
1879 nt_devmode->reserved1=devmode->reserved1;
1880 nt_devmode->reserved2=devmode->reserved2;
1881 nt_devmode->panningwidth=devmode->panningwidth;
1882 nt_devmode->panningheight=devmode->panningheight;
1885 * Only change private and driverextra if the incoming devmode
1886 * has a new one. JRA.
1889 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1890 SAFE_FREE(nt_devmode->nt_dev_private);
1891 nt_devmode->driverextra=devmode->driverextra;
1892 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1893 return False;
1894 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1897 *pp_nt_devmode = nt_devmode;
1899 return True;
1902 /********************************************************************
1903 * _spoolss_enddocprinter_internal.
1904 ********************************************************************/
1906 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1908 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1909 int snum;
1911 if (!Printer) {
1912 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1913 return WERR_BADFID;
1916 if (!get_printer_snum(p, handle, &snum, NULL))
1917 return WERR_BADFID;
1919 Printer->document_started=False;
1920 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1921 /* error codes unhandled so far ... */
1923 return WERR_OK;
1926 /********************************************************************
1927 * api_spoolss_closeprinter
1928 ********************************************************************/
1930 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1932 POLICY_HND *handle = &q_u->handle;
1934 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1936 if (Printer && Printer->document_started)
1937 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1939 if (!close_printer_handle(p, handle))
1940 return WERR_BADFID;
1942 /* clear the returned printer handle. Observed behavior
1943 from Win2k server. Don't think this really matters.
1944 Previous code just copied the value of the closed
1945 handle. --jerry */
1947 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1949 return WERR_OK;
1952 /********************************************************************
1953 * api_spoolss_deleteprinter
1955 ********************************************************************/
1957 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1959 POLICY_HND *handle = &q_u->handle;
1960 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1961 WERROR result;
1963 if (Printer && Printer->document_started)
1964 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1966 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1968 result = delete_printer_handle(p, handle);
1970 update_c_setprinter(False);
1972 return result;
1975 /*******************************************************************
1976 * static function to lookup the version id corresponding to an
1977 * long architecture string
1978 ******************************************************************/
1980 static int get_version_id (char * arch)
1982 int i;
1983 struct table_node archi_table[]= {
1985 {"Windows 4.0", "WIN40", 0 },
1986 {"Windows NT x86", "W32X86", 2 },
1987 {"Windows NT R4000", "W32MIPS", 2 },
1988 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1989 {"Windows NT PowerPC", "W32PPC", 2 },
1990 {"Windows IA64", "IA64", 3 },
1991 {"Windows x64", "x64", 3 },
1992 {NULL, "", -1 }
1995 for (i=0; archi_table[i].long_archi != NULL; i++)
1997 if (strcmp(arch, archi_table[i].long_archi) == 0)
1998 return (archi_table[i].version);
2001 return -1;
2004 /********************************************************************
2005 * _spoolss_deleteprinterdriver
2006 ********************************************************************/
2008 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2010 fstring driver;
2011 fstring arch;
2012 NT_PRINTER_DRIVER_INFO_LEVEL info;
2013 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2014 int version;
2015 WERROR status;
2016 WERROR status_win2k = WERR_ACCESS_DENIED;
2017 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2019 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2020 and not a printer admin, then fail */
2022 if ( (p->server_info->utok.uid != 0)
2023 && !user_has_privileges(p->server_info->ptok, &se_printop )
2024 && !token_contains_name_in_list(
2025 uidtoname(p->server_info->utok.uid), NULL,
2026 NULL, p->server_info->ptok,
2027 lp_printer_admin(-1)) )
2029 return WERR_ACCESS_DENIED;
2032 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2033 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2035 /* check that we have a valid driver name first */
2037 if ((version=get_version_id(arch)) == -1)
2038 return WERR_INVALID_ENVIRONMENT;
2040 ZERO_STRUCT(info);
2041 ZERO_STRUCT(info_win2k);
2043 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2045 /* try for Win2k driver if "Windows NT x86" */
2047 if ( version == 2 ) {
2048 version = 3;
2049 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2050 status = WERR_UNKNOWN_PRINTER_DRIVER;
2051 goto done;
2054 /* otherwise it was a failure */
2055 else {
2056 status = WERR_UNKNOWN_PRINTER_DRIVER;
2057 goto done;
2062 if (printer_driver_in_use(info.info_3)) {
2063 status = WERR_PRINTER_DRIVER_IN_USE;
2064 goto done;
2067 if ( version == 2 )
2069 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2071 /* if we get to here, we now have 2 driver info structures to remove */
2072 /* remove the Win2k driver first*/
2074 status_win2k = delete_printer_driver(
2075 p, info_win2k.info_3, 3, False );
2076 free_a_printer_driver( info_win2k, 3 );
2078 /* this should not have failed---if it did, report to client */
2079 if ( !W_ERROR_IS_OK(status_win2k) )
2081 status = status_win2k;
2082 goto done;
2087 status = delete_printer_driver(p, info.info_3, version, False);
2089 /* if at least one of the deletes succeeded return OK */
2091 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2092 status = WERR_OK;
2094 done:
2095 free_a_printer_driver( info, 3 );
2097 return status;
2100 /********************************************************************
2101 * spoolss_deleteprinterdriverex
2102 ********************************************************************/
2104 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2106 fstring driver;
2107 fstring arch;
2108 NT_PRINTER_DRIVER_INFO_LEVEL info;
2109 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2110 int version;
2111 uint32 flags = q_u->delete_flags;
2112 bool delete_files;
2113 WERROR status;
2114 WERROR status_win2k = WERR_ACCESS_DENIED;
2115 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2117 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2118 and not a printer admin, then fail */
2120 if ( (p->server_info->utok.uid != 0)
2121 && !user_has_privileges(p->server_info->ptok, &se_printop )
2122 && !token_contains_name_in_list(
2123 uidtoname(p->server_info->utok.uid), NULL, NULL,
2124 p->server_info->ptok, lp_printer_admin(-1)) )
2126 return WERR_ACCESS_DENIED;
2129 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2130 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2132 /* check that we have a valid driver name first */
2133 if ((version=get_version_id(arch)) == -1) {
2134 /* this is what NT returns */
2135 return WERR_INVALID_ENVIRONMENT;
2138 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2139 version = q_u->version;
2141 ZERO_STRUCT(info);
2142 ZERO_STRUCT(info_win2k);
2144 status = get_a_printer_driver(&info, 3, driver, arch, version);
2146 if ( !W_ERROR_IS_OK(status) )
2149 * if the client asked for a specific version,
2150 * or this is something other than Windows NT x86,
2151 * then we've failed
2154 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2155 goto done;
2157 /* try for Win2k driver if "Windows NT x86" */
2159 version = 3;
2160 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2161 status = WERR_UNKNOWN_PRINTER_DRIVER;
2162 goto done;
2166 if ( printer_driver_in_use(info.info_3) ) {
2167 status = WERR_PRINTER_DRIVER_IN_USE;
2168 goto done;
2172 * we have a couple of cases to consider.
2173 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2174 * then the delete should fail if **any** files overlap with
2175 * other drivers
2176 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2177 * non-overlapping files
2178 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2179 * is set, the do not delete any files
2180 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2183 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2185 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2187 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2188 /* no idea of the correct error here */
2189 status = WERR_ACCESS_DENIED;
2190 goto done;
2194 /* also check for W32X86/3 if necessary; maybe we already have? */
2196 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2197 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2200 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2201 /* no idea of the correct error here */
2202 free_a_printer_driver( info_win2k, 3 );
2203 status = WERR_ACCESS_DENIED;
2204 goto done;
2207 /* if we get to here, we now have 2 driver info structures to remove */
2208 /* remove the Win2k driver first*/
2210 status_win2k = delete_printer_driver(
2211 p, info_win2k.info_3, 3, delete_files);
2212 free_a_printer_driver( info_win2k, 3 );
2214 /* this should not have failed---if it did, report to client */
2216 if ( !W_ERROR_IS_OK(status_win2k) )
2217 goto done;
2221 status = delete_printer_driver(p, info.info_3, version, delete_files);
2223 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2224 status = WERR_OK;
2225 done:
2226 free_a_printer_driver( info, 3 );
2228 return status;
2232 /****************************************************************************
2233 Internal routine for retreiving printerdata
2234 ***************************************************************************/
2236 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2237 const char *key, const char *value, uint32 *type, uint8 **data,
2238 uint32 *needed, uint32 in_size )
2240 REGISTRY_VALUE *val;
2241 uint32 size;
2242 int data_len;
2244 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2245 return WERR_BADFILE;
2247 *type = regval_type( val );
2249 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2251 size = regval_size( val );
2253 /* copy the min(in_size, len) */
2255 if ( in_size ) {
2256 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2258 /* special case for 0 length values */
2259 if ( data_len ) {
2260 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2261 return WERR_NOMEM;
2263 else {
2264 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2265 return WERR_NOMEM;
2268 else
2269 *data = NULL;
2271 *needed = size;
2273 DEBUG(5,("get_printer_dataex: copy done\n"));
2275 return WERR_OK;
2278 /****************************************************************************
2279 Internal routine for removing printerdata
2280 ***************************************************************************/
2282 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2284 return delete_printer_data( printer->info_2, key, value );
2287 /****************************************************************************
2288 Internal routine for storing printerdata
2289 ***************************************************************************/
2291 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2292 uint32 type, uint8 *data, int real_len )
2294 /* the registry objects enforce uniqueness based on value name */
2296 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2299 /********************************************************************
2300 GetPrinterData on a printer server Handle.
2301 ********************************************************************/
2303 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2305 int i;
2307 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2309 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2310 *type = REG_DWORD;
2311 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2312 return WERR_NOMEM;
2313 SIVAL(*data, 0, 0x00);
2314 *needed = 0x4;
2315 return WERR_OK;
2318 if (!StrCaseCmp(value, "BeepEnabled")) {
2319 *type = REG_DWORD;
2320 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2321 return WERR_NOMEM;
2322 SIVAL(*data, 0, 0x00);
2323 *needed = 0x4;
2324 return WERR_OK;
2327 if (!StrCaseCmp(value, "EventLog")) {
2328 *type = REG_DWORD;
2329 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2330 return WERR_NOMEM;
2331 /* formally was 0x1b */
2332 SIVAL(*data, 0, 0x0);
2333 *needed = 0x4;
2334 return WERR_OK;
2337 if (!StrCaseCmp(value, "NetPopup")) {
2338 *type = REG_DWORD;
2339 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2340 return WERR_NOMEM;
2341 SIVAL(*data, 0, 0x00);
2342 *needed = 0x4;
2343 return WERR_OK;
2346 if (!StrCaseCmp(value, "MajorVersion")) {
2347 *type = REG_DWORD;
2348 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2349 return WERR_NOMEM;
2351 /* Windows NT 4.0 seems to not allow uploading of drivers
2352 to a server that reports 0x3 as the MajorVersion.
2353 need to investigate more how Win2k gets around this .
2354 -- jerry */
2356 if ( RA_WINNT == get_remote_arch() )
2357 SIVAL(*data, 0, 2);
2358 else
2359 SIVAL(*data, 0, 3);
2361 *needed = 0x4;
2362 return WERR_OK;
2365 if (!StrCaseCmp(value, "MinorVersion")) {
2366 *type = REG_DWORD;
2367 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2368 return WERR_NOMEM;
2369 SIVAL(*data, 0, 0);
2370 *needed = 0x4;
2371 return WERR_OK;
2374 /* REG_BINARY
2375 * uint32 size = 0x114
2376 * uint32 major = 5
2377 * uint32 minor = [0|1]
2378 * uint32 build = [2195|2600]
2379 * extra unicode string = e.g. "Service Pack 3"
2381 if (!StrCaseCmp(value, "OSVersion")) {
2382 *type = REG_BINARY;
2383 *needed = 0x114;
2385 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2386 return WERR_NOMEM;
2388 SIVAL(*data, 0, *needed); /* size */
2389 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2390 SIVAL(*data, 8, 0);
2391 SIVAL(*data, 12, 2195); /* build */
2393 /* leave extra string empty */
2395 return WERR_OK;
2399 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2400 const char *string="C:\\PRINTERS";
2401 *type = REG_SZ;
2402 *needed = 2*(strlen(string)+1);
2403 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2404 return WERR_NOMEM;
2405 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2407 /* it's done by hand ready to go on the wire */
2408 for (i=0; i<strlen(string); i++) {
2409 (*data)[2*i]=string[i];
2410 (*data)[2*i+1]='\0';
2412 return WERR_OK;
2415 if (!StrCaseCmp(value, "Architecture")) {
2416 const char *string="Windows NT x86";
2417 *type = REG_SZ;
2418 *needed = 2*(strlen(string)+1);
2419 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2420 return WERR_NOMEM;
2421 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2422 for (i=0; i<strlen(string); i++) {
2423 (*data)[2*i]=string[i];
2424 (*data)[2*i+1]='\0';
2426 return WERR_OK;
2429 if (!StrCaseCmp(value, "DsPresent")) {
2430 *type = REG_DWORD;
2431 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2432 return WERR_NOMEM;
2434 /* only show the publish check box if we are a
2435 memeber of a AD domain */
2437 if ( lp_security() == SEC_ADS )
2438 SIVAL(*data, 0, 0x01);
2439 else
2440 SIVAL(*data, 0, 0x00);
2442 *needed = 0x4;
2443 return WERR_OK;
2446 if (!StrCaseCmp(value, "DNSMachineName")) {
2447 const char *hostname = get_mydnsfullname();
2449 if (!hostname)
2450 return WERR_BADFILE;
2451 *type = REG_SZ;
2452 *needed = 2*(strlen(hostname)+1);
2453 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2454 return WERR_NOMEM;
2455 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2456 for (i=0; i<strlen(hostname); i++) {
2457 (*data)[2*i]=hostname[i];
2458 (*data)[2*i+1]='\0';
2460 return WERR_OK;
2464 return WERR_BADFILE;
2467 /********************************************************************
2468 * spoolss_getprinterdata
2469 ********************************************************************/
2471 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2473 POLICY_HND *handle = &q_u->handle;
2474 UNISTR2 *valuename = &q_u->valuename;
2475 uint32 in_size = q_u->size;
2476 uint32 *type = &r_u->type;
2477 uint32 *out_size = &r_u->size;
2478 uint8 **data = &r_u->data;
2479 uint32 *needed = &r_u->needed;
2480 WERROR status;
2481 fstring value;
2482 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2483 NT_PRINTER_INFO_LEVEL *printer = NULL;
2484 int snum = 0;
2487 * Reminder: when it's a string, the length is in BYTES
2488 * even if UNICODE is negociated.
2490 * JFM, 4/19/1999
2493 *out_size = in_size;
2495 /* in case of problem, return some default values */
2497 *needed = 0;
2498 *type = 0;
2500 DEBUG(4,("_spoolss_getprinterdata\n"));
2502 if ( !Printer ) {
2503 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2504 status = WERR_BADFID;
2505 goto done;
2508 unistr2_to_ascii(value, valuename, sizeof(value));
2510 if ( Printer->printer_type == SPLHND_SERVER )
2511 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2512 else
2514 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2515 status = WERR_BADFID;
2516 goto done;
2519 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2520 if ( !W_ERROR_IS_OK(status) )
2521 goto done;
2523 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2525 if ( strequal(value, "ChangeId") ) {
2526 *type = REG_DWORD;
2527 *needed = sizeof(uint32);
2528 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2529 status = WERR_NOMEM;
2530 goto done;
2532 SIVAL( *data, 0, printer->info_2->changeid );
2533 status = WERR_OK;
2535 else
2536 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2539 if (*needed > *out_size)
2540 status = WERR_MORE_DATA;
2542 done:
2543 if ( !W_ERROR_IS_OK(status) )
2545 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2547 /* reply this param doesn't exist */
2549 if ( *out_size ) {
2550 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2551 if ( printer )
2552 free_a_printer( &printer, 2 );
2553 return WERR_NOMEM;
2555 } else {
2556 *data = NULL;
2560 /* cleanup & exit */
2562 if ( printer )
2563 free_a_printer( &printer, 2 );
2565 return status;
2568 /*********************************************************
2569 Connect to the client machine.
2570 **********************************************************/
2572 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2573 struct sockaddr_storage *client_ss, const char *remote_machine)
2575 NTSTATUS ret;
2576 struct cli_state *the_cli;
2577 struct sockaddr_storage rm_addr;
2579 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2580 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2581 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2582 return False;
2585 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2586 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2587 return False;
2589 } else {
2590 char addr[INET6_ADDRSTRLEN];
2591 rm_addr = *client_ss;
2592 print_sockaddr(addr, sizeof(addr), &rm_addr);
2593 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2594 addr));
2597 /* setup the connection */
2599 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2600 &rm_addr, 0, "IPC$", "IPC",
2601 "", /* username */
2602 "", /* domain */
2603 "", /* password */
2604 0, lp_client_signing(), NULL );
2606 if ( !NT_STATUS_IS_OK( ret ) ) {
2607 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2608 remote_machine ));
2609 return False;
2612 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2613 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2614 cli_shutdown(the_cli);
2615 return False;
2619 * Ok - we have an anonymous connection to the IPC$ share.
2620 * Now start the NT Domain stuff :-).
2623 ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2624 if (!NT_STATUS_IS_OK(ret)) {
2625 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2626 remote_machine, nt_errstr(ret)));
2627 cli_shutdown(the_cli);
2628 return False;
2631 return True;
2634 /***************************************************************************
2635 Connect to the client.
2636 ****************************************************************************/
2638 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2639 uint32 localprinter, uint32 type,
2640 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2642 WERROR result;
2645 * If it's the first connection, contact the client
2646 * and connect to the IPC$ share anonymously
2648 if (smb_connections==0) {
2649 fstring unix_printer;
2651 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2653 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2654 return False;
2656 messaging_register(smbd_messaging_context(), NULL,
2657 MSG_PRINTER_NOTIFY2,
2658 receive_notify2_message_list);
2659 /* Tell the connections db we're now interested in printer
2660 * notify messages. */
2661 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2665 * Tell the specific printing tdb we want messages for this printer
2666 * by registering our PID.
2669 if (!print_notify_register_pid(snum))
2670 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2672 smb_connections++;
2674 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2675 talloc_tos(),
2676 printer,
2677 localprinter,
2678 type,
2679 handle);
2681 if (!W_ERROR_IS_OK(result))
2682 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2683 win_errstr(result)));
2685 return (W_ERROR_IS_OK(result));
2688 /********************************************************************
2689 * _spoolss_rffpcnex
2690 * ReplyFindFirstPrinterChangeNotifyEx
2692 * before replying OK: status=0 a rpc call is made to the workstation
2693 * asking ReplyOpenPrinter
2695 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2696 * called from api_spoolss_rffpcnex
2697 ********************************************************************/
2699 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2701 POLICY_HND *handle = &q_u->handle;
2702 uint32 flags = q_u->flags;
2703 uint32 options = q_u->options;
2704 UNISTR2 *localmachine = &q_u->localmachine;
2705 uint32 printerlocal = q_u->printerlocal;
2706 int snum = -1;
2707 SPOOL_NOTIFY_OPTION *option = q_u->option;
2708 struct sockaddr_storage client_ss;
2710 /* store the notify value in the printer struct */
2712 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2714 if (!Printer) {
2715 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2716 return WERR_BADFID;
2719 Printer->notify.flags=flags;
2720 Printer->notify.options=options;
2721 Printer->notify.printerlocal=printerlocal;
2723 if (Printer->notify.option)
2724 free_spool_notify_option(&Printer->notify.option);
2726 Printer->notify.option=dup_spool_notify_option(option);
2728 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2729 sizeof(Printer->notify.localmachine));
2731 /* Connect to the client machine and send a ReplyOpenPrinter */
2733 if ( Printer->printer_type == SPLHND_SERVER)
2734 snum = -1;
2735 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2736 !get_printer_snum(p, handle, &snum, NULL) )
2737 return WERR_BADFID;
2739 if (!interpret_string_addr(&client_ss, p->client_address,
2740 AI_NUMERICHOST)) {
2741 return WERR_SERVER_UNAVAILABLE;
2744 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2745 Printer->notify.printerlocal, 1,
2746 &Printer->notify.client_hnd, &client_ss))
2747 return WERR_SERVER_UNAVAILABLE;
2749 Printer->notify.client_connected=True;
2751 return WERR_OK;
2754 /*******************************************************************
2755 * fill a notify_info_data with the servername
2756 ********************************************************************/
2758 void spoolss_notify_server_name(int snum,
2759 SPOOL_NOTIFY_INFO_DATA *data,
2760 print_queue_struct *queue,
2761 NT_PRINTER_INFO_LEVEL *printer,
2762 TALLOC_CTX *mem_ctx)
2764 smb_ucs2_t *temp = NULL;
2765 uint32 len;
2767 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2768 if (len == (uint32)-1) {
2769 len = 0;
2772 data->notify_data.data.length = len;
2773 if (len) {
2774 data->notify_data.data.string = (uint16 *)temp;
2775 } else {
2776 data->notify_data.data.string = NULL;
2780 /*******************************************************************
2781 * fill a notify_info_data with the printername (not including the servername).
2782 ********************************************************************/
2784 void spoolss_notify_printer_name(int snum,
2785 SPOOL_NOTIFY_INFO_DATA *data,
2786 print_queue_struct *queue,
2787 NT_PRINTER_INFO_LEVEL *printer,
2788 TALLOC_CTX *mem_ctx)
2790 smb_ucs2_t *temp = NULL;
2791 uint32 len;
2793 /* the notify name should not contain the \\server\ part */
2794 char *p = strrchr(printer->info_2->printername, '\\');
2796 if (!p) {
2797 p = printer->info_2->printername;
2798 } else {
2799 p++;
2802 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2803 if (len == (uint32)-1) {
2804 len = 0;
2807 data->notify_data.data.length = len;
2808 if (len) {
2809 data->notify_data.data.string = (uint16 *)temp;
2810 } else {
2811 data->notify_data.data.string = NULL;
2815 /*******************************************************************
2816 * fill a notify_info_data with the servicename
2817 ********************************************************************/
2819 void spoolss_notify_share_name(int snum,
2820 SPOOL_NOTIFY_INFO_DATA *data,
2821 print_queue_struct *queue,
2822 NT_PRINTER_INFO_LEVEL *printer,
2823 TALLOC_CTX *mem_ctx)
2825 smb_ucs2_t *temp = NULL;
2826 uint32 len;
2828 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2829 if (len == (uint32)-1) {
2830 len = 0;
2833 data->notify_data.data.length = len;
2834 if (len) {
2835 data->notify_data.data.string = (uint16 *)temp;
2836 } else {
2837 data->notify_data.data.string = NULL;
2842 /*******************************************************************
2843 * fill a notify_info_data with the port name
2844 ********************************************************************/
2846 void spoolss_notify_port_name(int snum,
2847 SPOOL_NOTIFY_INFO_DATA *data,
2848 print_queue_struct *queue,
2849 NT_PRINTER_INFO_LEVEL *printer,
2850 TALLOC_CTX *mem_ctx)
2852 smb_ucs2_t *temp = NULL;
2853 uint32 len;
2855 /* even if it's strange, that's consistant in all the code */
2857 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2858 if (len == (uint32)-1) {
2859 len = 0;
2862 data->notify_data.data.length = len;
2863 if (len) {
2864 data->notify_data.data.string = (uint16 *)temp;
2865 } else {
2866 data->notify_data.data.string = NULL;
2870 /*******************************************************************
2871 * fill a notify_info_data with the printername
2872 * but it doesn't exist, have to see what to do
2873 ********************************************************************/
2875 void spoolss_notify_driver_name(int snum,
2876 SPOOL_NOTIFY_INFO_DATA *data,
2877 print_queue_struct *queue,
2878 NT_PRINTER_INFO_LEVEL *printer,
2879 TALLOC_CTX *mem_ctx)
2881 smb_ucs2_t *temp = NULL;
2882 uint32 len;
2884 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2885 if (len == (uint32)-1) {
2886 len = 0;
2889 data->notify_data.data.length = len;
2890 if (len) {
2891 data->notify_data.data.string = (uint16 *)temp;
2892 } else {
2893 data->notify_data.data.string = NULL;
2897 /*******************************************************************
2898 * fill a notify_info_data with the comment
2899 ********************************************************************/
2901 void spoolss_notify_comment(int snum,
2902 SPOOL_NOTIFY_INFO_DATA *data,
2903 print_queue_struct *queue,
2904 NT_PRINTER_INFO_LEVEL *printer,
2905 TALLOC_CTX *mem_ctx)
2907 smb_ucs2_t *temp = NULL;
2908 uint32 len;
2910 if (*printer->info_2->comment == '\0')
2911 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2912 else
2913 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2915 if (len == (uint32)-1) {
2916 len = 0;
2918 data->notify_data.data.length = len;
2919 if (len) {
2920 data->notify_data.data.string = (uint16 *)temp;
2921 } else {
2922 data->notify_data.data.string = NULL;
2926 /*******************************************************************
2927 * fill a notify_info_data with the comment
2928 * location = "Room 1, floor 2, building 3"
2929 ********************************************************************/
2931 void spoolss_notify_location(int snum,
2932 SPOOL_NOTIFY_INFO_DATA *data,
2933 print_queue_struct *queue,
2934 NT_PRINTER_INFO_LEVEL *printer,
2935 TALLOC_CTX *mem_ctx)
2937 smb_ucs2_t *temp = NULL;
2938 uint32 len;
2940 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2941 if (len == (uint32)-1) {
2942 len = 0;
2945 data->notify_data.data.length = len;
2946 if (len) {
2947 data->notify_data.data.string = (uint16 *)temp;
2948 } else {
2949 data->notify_data.data.string = NULL;
2953 /*******************************************************************
2954 * fill a notify_info_data with the device mode
2955 * jfm:xxxx don't to it for know but that's a real problem !!!
2956 ********************************************************************/
2958 static void spoolss_notify_devmode(int snum,
2959 SPOOL_NOTIFY_INFO_DATA *data,
2960 print_queue_struct *queue,
2961 NT_PRINTER_INFO_LEVEL *printer,
2962 TALLOC_CTX *mem_ctx)
2964 /* for a dummy implementation we have to zero the fields */
2965 data->notify_data.data.length = 0;
2966 data->notify_data.data.string = NULL;
2969 /*******************************************************************
2970 * fill a notify_info_data with the separator file name
2971 ********************************************************************/
2973 void spoolss_notify_sepfile(int snum,
2974 SPOOL_NOTIFY_INFO_DATA *data,
2975 print_queue_struct *queue,
2976 NT_PRINTER_INFO_LEVEL *printer,
2977 TALLOC_CTX *mem_ctx)
2979 smb_ucs2_t *temp = NULL;
2980 uint32 len;
2982 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2983 if (len == (uint32)-1) {
2984 len = 0;
2987 data->notify_data.data.length = len;
2988 if (len) {
2989 data->notify_data.data.string = (uint16 *)temp;
2990 } else {
2991 data->notify_data.data.string = NULL;
2995 /*******************************************************************
2996 * fill a notify_info_data with the print processor
2997 * jfm:xxxx return always winprint to indicate we don't do anything to it
2998 ********************************************************************/
3000 void spoolss_notify_print_processor(int snum,
3001 SPOOL_NOTIFY_INFO_DATA *data,
3002 print_queue_struct *queue,
3003 NT_PRINTER_INFO_LEVEL *printer,
3004 TALLOC_CTX *mem_ctx)
3006 smb_ucs2_t *temp = NULL;
3007 uint32 len;
3009 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
3010 if (len == (uint32)-1) {
3011 len = 0;
3014 data->notify_data.data.length = len;
3015 if (len) {
3016 data->notify_data.data.string = (uint16 *)temp;
3017 } else {
3018 data->notify_data.data.string = NULL;
3022 /*******************************************************************
3023 * fill a notify_info_data with the print processor options
3024 * jfm:xxxx send an empty string
3025 ********************************************************************/
3027 void spoolss_notify_parameters(int snum,
3028 SPOOL_NOTIFY_INFO_DATA *data,
3029 print_queue_struct *queue,
3030 NT_PRINTER_INFO_LEVEL *printer,
3031 TALLOC_CTX *mem_ctx)
3033 smb_ucs2_t *temp = NULL;
3034 uint32 len;
3036 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3037 if (len == (uint32)-1) {
3038 len = 0;
3041 data->notify_data.data.length = len;
3042 if (len) {
3043 data->notify_data.data.string = (uint16 *)temp;
3044 } else {
3045 data->notify_data.data.string = NULL;
3049 /*******************************************************************
3050 * fill a notify_info_data with the data type
3051 * jfm:xxxx always send RAW as data type
3052 ********************************************************************/
3054 void spoolss_notify_datatype(int snum,
3055 SPOOL_NOTIFY_INFO_DATA *data,
3056 print_queue_struct *queue,
3057 NT_PRINTER_INFO_LEVEL *printer,
3058 TALLOC_CTX *mem_ctx)
3060 smb_ucs2_t *temp = NULL;
3061 uint32 len;
3063 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3064 if (len == (uint32)-1) {
3065 len = 0;
3068 data->notify_data.data.length = len;
3069 if (len) {
3070 data->notify_data.data.string = (uint16 *)temp;
3071 } else {
3072 data->notify_data.data.string = NULL;
3076 /*******************************************************************
3077 * fill a notify_info_data with the security descriptor
3078 * jfm:xxxx send an null pointer to say no security desc
3079 * have to implement security before !
3080 ********************************************************************/
3082 static void spoolss_notify_security_desc(int snum,
3083 SPOOL_NOTIFY_INFO_DATA *data,
3084 print_queue_struct *queue,
3085 NT_PRINTER_INFO_LEVEL *printer,
3086 TALLOC_CTX *mem_ctx)
3088 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3089 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3092 /*******************************************************************
3093 * fill a notify_info_data with the attributes
3094 * jfm:xxxx a samba printer is always shared
3095 ********************************************************************/
3097 void spoolss_notify_attributes(int snum,
3098 SPOOL_NOTIFY_INFO_DATA *data,
3099 print_queue_struct *queue,
3100 NT_PRINTER_INFO_LEVEL *printer,
3101 TALLOC_CTX *mem_ctx)
3103 data->notify_data.value[0] = printer->info_2->attributes;
3104 data->notify_data.value[1] = 0;
3107 /*******************************************************************
3108 * fill a notify_info_data with the priority
3109 ********************************************************************/
3111 static void spoolss_notify_priority(int snum,
3112 SPOOL_NOTIFY_INFO_DATA *data,
3113 print_queue_struct *queue,
3114 NT_PRINTER_INFO_LEVEL *printer,
3115 TALLOC_CTX *mem_ctx)
3117 data->notify_data.value[0] = printer->info_2->priority;
3118 data->notify_data.value[1] = 0;
3121 /*******************************************************************
3122 * fill a notify_info_data with the default priority
3123 ********************************************************************/
3125 static void spoolss_notify_default_priority(int snum,
3126 SPOOL_NOTIFY_INFO_DATA *data,
3127 print_queue_struct *queue,
3128 NT_PRINTER_INFO_LEVEL *printer,
3129 TALLOC_CTX *mem_ctx)
3131 data->notify_data.value[0] = printer->info_2->default_priority;
3132 data->notify_data.value[1] = 0;
3135 /*******************************************************************
3136 * fill a notify_info_data with the start time
3137 ********************************************************************/
3139 static void spoolss_notify_start_time(int snum,
3140 SPOOL_NOTIFY_INFO_DATA *data,
3141 print_queue_struct *queue,
3142 NT_PRINTER_INFO_LEVEL *printer,
3143 TALLOC_CTX *mem_ctx)
3145 data->notify_data.value[0] = printer->info_2->starttime;
3146 data->notify_data.value[1] = 0;
3149 /*******************************************************************
3150 * fill a notify_info_data with the until time
3151 ********************************************************************/
3153 static void spoolss_notify_until_time(int snum,
3154 SPOOL_NOTIFY_INFO_DATA *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3159 data->notify_data.value[0] = printer->info_2->untiltime;
3160 data->notify_data.value[1] = 0;
3163 /*******************************************************************
3164 * fill a notify_info_data with the status
3165 ********************************************************************/
3167 static void spoolss_notify_status(int snum,
3168 SPOOL_NOTIFY_INFO_DATA *data,
3169 print_queue_struct *queue,
3170 NT_PRINTER_INFO_LEVEL *printer,
3171 TALLOC_CTX *mem_ctx)
3173 print_status_struct status;
3175 print_queue_length(snum, &status);
3176 data->notify_data.value[0]=(uint32) status.status;
3177 data->notify_data.value[1] = 0;
3180 /*******************************************************************
3181 * fill a notify_info_data with the number of jobs queued
3182 ********************************************************************/
3184 void spoolss_notify_cjobs(int snum,
3185 SPOOL_NOTIFY_INFO_DATA *data,
3186 print_queue_struct *queue,
3187 NT_PRINTER_INFO_LEVEL *printer,
3188 TALLOC_CTX *mem_ctx)
3190 data->notify_data.value[0] = print_queue_length(snum, NULL);
3191 data->notify_data.value[1] = 0;
3194 /*******************************************************************
3195 * fill a notify_info_data with the average ppm
3196 ********************************************************************/
3198 static void spoolss_notify_average_ppm(int snum,
3199 SPOOL_NOTIFY_INFO_DATA *data,
3200 print_queue_struct *queue,
3201 NT_PRINTER_INFO_LEVEL *printer,
3202 TALLOC_CTX *mem_ctx)
3204 /* always respond 8 pages per minutes */
3205 /* a little hard ! */
3206 data->notify_data.value[0] = printer->info_2->averageppm;
3207 data->notify_data.value[1] = 0;
3210 /*******************************************************************
3211 * fill a notify_info_data with username
3212 ********************************************************************/
3214 static void spoolss_notify_username(int snum,
3215 SPOOL_NOTIFY_INFO_DATA *data,
3216 print_queue_struct *queue,
3217 NT_PRINTER_INFO_LEVEL *printer,
3218 TALLOC_CTX *mem_ctx)
3220 smb_ucs2_t *temp = NULL;
3221 uint32 len;
3223 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3224 if (len == (uint32)-1) {
3225 len = 0;
3228 data->notify_data.data.length = len;
3229 if (len) {
3230 data->notify_data.data.string = (uint16 *)temp;
3231 } else {
3232 data->notify_data.data.string = NULL;
3236 /*******************************************************************
3237 * fill a notify_info_data with job status
3238 ********************************************************************/
3240 static void spoolss_notify_job_status(int snum,
3241 SPOOL_NOTIFY_INFO_DATA *data,
3242 print_queue_struct *queue,
3243 NT_PRINTER_INFO_LEVEL *printer,
3244 TALLOC_CTX *mem_ctx)
3246 data->notify_data.value[0]=nt_printj_status(queue->status);
3247 data->notify_data.value[1] = 0;
3250 /*******************************************************************
3251 * fill a notify_info_data with job name
3252 ********************************************************************/
3254 static void spoolss_notify_job_name(int snum,
3255 SPOOL_NOTIFY_INFO_DATA *data,
3256 print_queue_struct *queue,
3257 NT_PRINTER_INFO_LEVEL *printer,
3258 TALLOC_CTX *mem_ctx)
3260 smb_ucs2_t *temp = NULL;
3261 uint32 len;
3263 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3264 if (len == (uint32)-1) {
3265 len = 0;
3268 data->notify_data.data.length = len;
3269 if (len) {
3270 data->notify_data.data.string = (uint16 *)temp;
3271 } else {
3272 data->notify_data.data.string = NULL;
3276 /*******************************************************************
3277 * fill a notify_info_data with job status
3278 ********************************************************************/
3280 static void spoolss_notify_job_status_string(int snum,
3281 SPOOL_NOTIFY_INFO_DATA *data,
3282 print_queue_struct *queue,
3283 NT_PRINTER_INFO_LEVEL *printer,
3284 TALLOC_CTX *mem_ctx)
3287 * Now we're returning job status codes we just return a "" here. JRA.
3290 const char *p = "";
3291 smb_ucs2_t *temp = NULL;
3292 uint32 len;
3294 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3295 p = "unknown";
3297 switch (queue->status) {
3298 case LPQ_QUEUED:
3299 p = "Queued";
3300 break;
3301 case LPQ_PAUSED:
3302 p = ""; /* NT provides the paused string */
3303 break;
3304 case LPQ_SPOOLING:
3305 p = "Spooling";
3306 break;
3307 case LPQ_PRINTING:
3308 p = "Printing";
3309 break;
3311 #endif /* NO LONGER NEEDED. */
3313 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3314 if (len == (uint32)-1) {
3315 len = 0;
3318 data->notify_data.data.length = len;
3319 if (len) {
3320 data->notify_data.data.string = (uint16 *)temp;
3321 } else {
3322 data->notify_data.data.string = NULL;
3326 /*******************************************************************
3327 * fill a notify_info_data with job time
3328 ********************************************************************/
3330 static void spoolss_notify_job_time(int snum,
3331 SPOOL_NOTIFY_INFO_DATA *data,
3332 print_queue_struct *queue,
3333 NT_PRINTER_INFO_LEVEL *printer,
3334 TALLOC_CTX *mem_ctx)
3336 data->notify_data.value[0]=0x0;
3337 data->notify_data.value[1]=0;
3340 /*******************************************************************
3341 * fill a notify_info_data with job size
3342 ********************************************************************/
3344 static void spoolss_notify_job_size(int snum,
3345 SPOOL_NOTIFY_INFO_DATA *data,
3346 print_queue_struct *queue,
3347 NT_PRINTER_INFO_LEVEL *printer,
3348 TALLOC_CTX *mem_ctx)
3350 data->notify_data.value[0]=queue->size;
3351 data->notify_data.value[1]=0;
3354 /*******************************************************************
3355 * fill a notify_info_data with page info
3356 ********************************************************************/
3357 static void spoolss_notify_total_pages(int snum,
3358 SPOOL_NOTIFY_INFO_DATA *data,
3359 print_queue_struct *queue,
3360 NT_PRINTER_INFO_LEVEL *printer,
3361 TALLOC_CTX *mem_ctx)
3363 data->notify_data.value[0]=queue->page_count;
3364 data->notify_data.value[1]=0;
3367 /*******************************************************************
3368 * fill a notify_info_data with pages printed info.
3369 ********************************************************************/
3370 static void spoolss_notify_pages_printed(int snum,
3371 SPOOL_NOTIFY_INFO_DATA *data,
3372 print_queue_struct *queue,
3373 NT_PRINTER_INFO_LEVEL *printer,
3374 TALLOC_CTX *mem_ctx)
3376 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3377 data->notify_data.value[1]=0;
3380 /*******************************************************************
3381 Fill a notify_info_data with job position.
3382 ********************************************************************/
3384 static void spoolss_notify_job_position(int snum,
3385 SPOOL_NOTIFY_INFO_DATA *data,
3386 print_queue_struct *queue,
3387 NT_PRINTER_INFO_LEVEL *printer,
3388 TALLOC_CTX *mem_ctx)
3390 data->notify_data.value[0]=queue->job;
3391 data->notify_data.value[1]=0;
3394 /*******************************************************************
3395 Fill a notify_info_data with submitted time.
3396 ********************************************************************/
3398 static void spoolss_notify_submitted_time(int snum,
3399 SPOOL_NOTIFY_INFO_DATA *data,
3400 print_queue_struct *queue,
3401 NT_PRINTER_INFO_LEVEL *printer,
3402 TALLOC_CTX *mem_ctx)
3404 struct tm *t;
3405 uint32 len;
3406 SYSTEMTIME st;
3407 char *p;
3409 t=gmtime(&queue->time);
3411 len = sizeof(SYSTEMTIME);
3413 data->notify_data.data.length = len;
3414 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3416 if (!data->notify_data.data.string) {
3417 data->notify_data.data.length = 0;
3418 return;
3421 make_systemtime(&st, t);
3424 * Systemtime must be linearized as a set of UINT16's.
3425 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3428 p = (char *)data->notify_data.data.string;
3429 SSVAL(p, 0, st.year);
3430 SSVAL(p, 2, st.month);
3431 SSVAL(p, 4, st.dayofweek);
3432 SSVAL(p, 6, st.day);
3433 SSVAL(p, 8, st.hour);
3434 SSVAL(p, 10, st.minute);
3435 SSVAL(p, 12, st.second);
3436 SSVAL(p, 14, st.milliseconds);
3439 struct s_notify_info_data_table
3441 uint16 type;
3442 uint16 field;
3443 const char *name;
3444 uint32 size;
3445 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3446 print_queue_struct *queue,
3447 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3450 /* A table describing the various print notification constants and
3451 whether the notification data is a pointer to a variable sized
3452 buffer, a one value uint32 or a two value uint32. */
3454 static const struct s_notify_info_data_table notify_info_data_table[] =
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3505 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3508 /*******************************************************************
3509 Return the size of info_data structure.
3510 ********************************************************************/
3512 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3514 int i=0;
3516 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3517 if ( (notify_info_data_table[i].type == type)
3518 && (notify_info_data_table[i].field == field) ) {
3519 switch(notify_info_data_table[i].size) {
3520 case NOTIFY_ONE_VALUE:
3521 case NOTIFY_TWO_VALUE:
3522 return 1;
3523 case NOTIFY_STRING:
3524 return 2;
3526 /* The only pointer notify data I have seen on
3527 the wire is the submitted time and this has
3528 the notify size set to 4. -tpot */
3530 case NOTIFY_POINTER:
3531 return 4;
3533 case NOTIFY_SECDESC:
3534 return 5;
3539 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3541 return 0;
3544 /*******************************************************************
3545 Return the type of notify_info_data.
3546 ********************************************************************/
3548 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3550 uint32 i=0;
3552 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3553 if (notify_info_data_table[i].type == type &&
3554 notify_info_data_table[i].field == field)
3555 return notify_info_data_table[i].size;
3558 return 0;
3561 /****************************************************************************
3562 ****************************************************************************/
3564 static bool search_notify(uint16 type, uint16 field, int *value)
3566 int i;
3568 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3569 if (notify_info_data_table[i].type == type &&
3570 notify_info_data_table[i].field == field &&
3571 notify_info_data_table[i].fn != NULL) {
3572 *value = i;
3573 return True;
3577 return False;
3580 /****************************************************************************
3581 ****************************************************************************/
3583 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3585 info_data->type = type;
3586 info_data->field = field;
3587 info_data->reserved = 0;
3589 info_data->size = size_of_notify_info_data(type, field);
3590 info_data->enc_type = type_of_notify_info_data(type, field);
3592 info_data->id = id;
3595 /*******************************************************************
3597 * fill a notify_info struct with info asked
3599 ********************************************************************/
3601 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3602 snum, SPOOL_NOTIFY_OPTION_TYPE
3603 *option_type, uint32 id,
3604 TALLOC_CTX *mem_ctx)
3606 int field_num,j;
3607 uint16 type;
3608 uint16 field;
3610 SPOOL_NOTIFY_INFO_DATA *current_data;
3611 NT_PRINTER_INFO_LEVEL *printer = NULL;
3612 print_queue_struct *queue=NULL;
3614 type=option_type->type;
3616 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3617 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3618 option_type->count, lp_servicename(snum)));
3620 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3621 return False;
3623 for(field_num=0; field_num<option_type->count; field_num++) {
3624 field = option_type->fields[field_num];
3626 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3628 if (!search_notify(type, field, &j) )
3629 continue;
3631 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3632 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3633 free_a_printer(&printer, 2);
3634 return False;
3637 current_data = &info->data[info->count];
3639 construct_info_data(current_data, type, field, id);
3641 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3642 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3644 notify_info_data_table[j].fn(snum, current_data, queue,
3645 printer, mem_ctx);
3647 info->count++;
3650 free_a_printer(&printer, 2);
3651 return True;
3654 /*******************************************************************
3656 * fill a notify_info struct with info asked
3658 ********************************************************************/
3660 static bool construct_notify_jobs_info(print_queue_struct *queue,
3661 SPOOL_NOTIFY_INFO *info,
3662 NT_PRINTER_INFO_LEVEL *printer,
3663 int snum, SPOOL_NOTIFY_OPTION_TYPE
3664 *option_type, uint32 id,
3665 TALLOC_CTX *mem_ctx)
3667 int field_num,j;
3668 uint16 type;
3669 uint16 field;
3671 SPOOL_NOTIFY_INFO_DATA *current_data;
3673 DEBUG(4,("construct_notify_jobs_info\n"));
3675 type = option_type->type;
3677 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3678 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3679 option_type->count));
3681 for(field_num=0; field_num<option_type->count; field_num++) {
3682 field = option_type->fields[field_num];
3684 if (!search_notify(type, field, &j) )
3685 continue;
3687 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3688 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3689 return False;
3692 current_data=&(info->data[info->count]);
3694 construct_info_data(current_data, type, field, id);
3695 notify_info_data_table[j].fn(snum, current_data, queue,
3696 printer, mem_ctx);
3697 info->count++;
3700 return True;
3704 * JFM: The enumeration is not that simple, it's even non obvious.
3706 * let's take an example: I want to monitor the PRINTER SERVER for
3707 * the printer's name and the number of jobs currently queued.
3708 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3709 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3711 * I have 3 printers on the back of my server.
3713 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3714 * structures.
3715 * Number Data Id
3716 * 1 printer 1 name 1
3717 * 2 printer 1 cjob 1
3718 * 3 printer 2 name 2
3719 * 4 printer 2 cjob 2
3720 * 5 printer 3 name 3
3721 * 6 printer 3 name 3
3723 * that's the print server case, the printer case is even worse.
3726 /*******************************************************************
3728 * enumerate all printers on the printserver
3729 * fill a notify_info struct with info asked
3731 ********************************************************************/
3733 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3734 SPOOL_NOTIFY_INFO *info,
3735 TALLOC_CTX *mem_ctx)
3737 int snum;
3738 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3739 int n_services=lp_numservices();
3740 int i;
3741 SPOOL_NOTIFY_OPTION *option;
3742 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3744 DEBUG(4,("printserver_notify_info\n"));
3746 if (!Printer)
3747 return WERR_BADFID;
3749 option=Printer->notify.option;
3750 info->version=2;
3751 info->data=NULL;
3752 info->count=0;
3754 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3755 sending a ffpcn() request first */
3757 if ( !option )
3758 return WERR_BADFID;
3760 for (i=0; i<option->count; i++) {
3761 option_type=&(option->ctr.type[i]);
3763 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3764 continue;
3766 for (snum=0; snum<n_services; snum++)
3768 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3769 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3773 #if 0
3775 * Debugging information, don't delete.
3778 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3779 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3780 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3782 for (i=0; i<info->count; i++) {
3783 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3784 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3785 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3787 #endif
3789 return WERR_OK;
3792 /*******************************************************************
3794 * fill a notify_info struct with info asked
3796 ********************************************************************/
3798 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3799 TALLOC_CTX *mem_ctx)
3801 int snum;
3802 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3803 int i;
3804 uint32 id;
3805 SPOOL_NOTIFY_OPTION *option;
3806 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3807 int count,j;
3808 print_queue_struct *queue=NULL;
3809 print_status_struct status;
3811 DEBUG(4,("printer_notify_info\n"));
3813 if (!Printer)
3814 return WERR_BADFID;
3816 option=Printer->notify.option;
3817 id = 0x0;
3818 info->version=2;
3819 info->data=NULL;
3820 info->count=0;
3822 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3823 sending a ffpcn() request first */
3825 if ( !option )
3826 return WERR_BADFID;
3828 get_printer_snum(p, hnd, &snum, NULL);
3830 for (i=0; i<option->count; i++) {
3831 option_type=&option->ctr.type[i];
3833 switch ( option_type->type ) {
3834 case PRINTER_NOTIFY_TYPE:
3835 if(construct_notify_printer_info(Printer, info, snum,
3836 option_type, id,
3837 mem_ctx))
3838 id--;
3839 break;
3841 case JOB_NOTIFY_TYPE: {
3842 NT_PRINTER_INFO_LEVEL *printer = NULL;
3844 count = print_queue_status(snum, &queue, &status);
3846 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3847 goto done;
3849 for (j=0; j<count; j++) {
3850 construct_notify_jobs_info(&queue[j], info,
3851 printer, snum,
3852 option_type,
3853 queue[j].job,
3854 mem_ctx);
3857 free_a_printer(&printer, 2);
3859 done:
3860 SAFE_FREE(queue);
3861 break;
3867 * Debugging information, don't delete.
3870 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3871 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3872 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3874 for (i=0; i<info->count; i++) {
3875 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3876 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3877 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3880 return WERR_OK;
3883 /********************************************************************
3884 * spoolss_rfnpcnex
3885 ********************************************************************/
3887 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3889 POLICY_HND *handle = &q_u->handle;
3890 SPOOL_NOTIFY_INFO *info = &r_u->info;
3892 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3893 WERROR result = WERR_BADFID;
3895 /* we always have a NOTIFY_INFO struct */
3896 r_u->info_ptr=0x1;
3898 if (!Printer) {
3899 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3900 OUR_HANDLE(handle)));
3901 goto done;
3904 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3907 * We are now using the change value, and
3908 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3909 * I don't have a global notification system, I'm sending back all the
3910 * informations even when _NOTHING_ has changed.
3913 /* We need to keep track of the change value to send back in
3914 RRPCN replies otherwise our updates are ignored. */
3916 Printer->notify.fnpcn = True;
3918 if (Printer->notify.client_connected) {
3919 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3920 Printer->notify.change = q_u->change;
3923 /* just ignore the SPOOL_NOTIFY_OPTION */
3925 switch (Printer->printer_type) {
3926 case SPLHND_SERVER:
3927 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3928 break;
3930 case SPLHND_PRINTER:
3931 result = printer_notify_info(p, handle, info, p->mem_ctx);
3932 break;
3935 Printer->notify.fnpcn = False;
3937 done:
3938 return result;
3941 /********************************************************************
3942 * construct_printer_info_0
3943 * fill a printer_info_0 struct
3944 ********************************************************************/
3946 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3948 char *chaine = NULL;
3949 int count;
3950 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3951 counter_printer_0 *session_counter;
3952 uint32 global_counter;
3953 struct tm *t;
3954 time_t setuptime;
3955 print_status_struct status;
3956 TALLOC_CTX *ctx = talloc_tos();
3958 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3959 return False;
3961 init_unistr(&printer->printername, ntprinter->info_2->printername);
3963 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3964 if (!chaine) {
3965 free_a_printer(&ntprinter,2);
3966 return false;
3969 count = print_queue_length(snum, &status);
3971 /* check if we already have a counter for this printer */
3972 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3973 if (session_counter->snum == snum)
3974 break;
3977 init_unistr(&printer->servername, chaine);
3979 /* it's the first time, add it to the list */
3980 if (session_counter==NULL) {
3981 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3982 free_a_printer(&ntprinter, 2);
3983 return False;
3985 ZERO_STRUCTP(session_counter);
3986 session_counter->snum=snum;
3987 session_counter->counter=0;
3988 DLIST_ADD(counter_list, session_counter);
3991 /* increment it */
3992 session_counter->counter++;
3994 /* JFM:
3995 * the global_counter should be stored in a TDB as it's common to all the clients
3996 * and should be zeroed on samba startup
3998 global_counter=session_counter->counter;
3999 printer->cjobs = count;
4000 printer->total_jobs = 0;
4001 printer->total_bytes = 0;
4003 setuptime = (time_t)ntprinter->info_2->setuptime;
4004 t=gmtime(&setuptime);
4006 printer->year = t->tm_year+1900;
4007 printer->month = t->tm_mon+1;
4008 printer->dayofweek = t->tm_wday;
4009 printer->day = t->tm_mday;
4010 printer->hour = t->tm_hour;
4011 printer->minute = t->tm_min;
4012 printer->second = t->tm_sec;
4013 printer->milliseconds = 0;
4015 printer->global_counter = global_counter;
4016 printer->total_pages = 0;
4018 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4019 printer->major_version = 0x0005; /* NT 5 */
4020 printer->build_version = 0x0893; /* build 2195 */
4022 printer->unknown7 = 0x1;
4023 printer->unknown8 = 0x0;
4024 printer->unknown9 = 0x0;
4025 printer->session_counter = session_counter->counter;
4026 printer->unknown11 = 0x0;
4027 printer->printer_errors = 0x0; /* number of print failure */
4028 printer->unknown13 = 0x0;
4029 printer->unknown14 = 0x1;
4030 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4031 printer->unknown16 = 0x0;
4032 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4033 printer->unknown18 = 0x0;
4034 printer->status = nt_printq_status(status.status);
4035 printer->unknown20 = 0x0;
4036 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4037 printer->unknown22 = 0x0;
4038 printer->unknown23 = 0x6; /* 6 ???*/
4039 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4040 printer->unknown25 = 0;
4041 printer->unknown26 = 0;
4042 printer->unknown27 = 0;
4043 printer->unknown28 = 0;
4044 printer->unknown29 = 0;
4046 free_a_printer(&ntprinter,2);
4047 return (True);
4050 /********************************************************************
4051 * construct_printer_info_1
4052 * fill a printer_info_1 struct
4053 ********************************************************************/
4054 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4056 char *chaine = NULL;
4057 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4058 TALLOC_CTX *ctx = talloc_tos();
4060 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4061 return false;
4063 printer->flags=flags;
4065 if (*ntprinter->info_2->comment == '\0') {
4066 init_unistr(&printer->comment, lp_comment(snum));
4067 chaine = talloc_asprintf(ctx,
4068 "%s,%s,%s", ntprinter->info_2->printername,
4069 ntprinter->info_2->drivername, lp_comment(snum));
4071 else {
4072 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4073 chaine = talloc_asprintf(ctx,
4074 "%s,%s,%s", ntprinter->info_2->printername,
4075 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4078 if (!chaine) {
4079 free_a_printer(&ntprinter,2);
4080 return false;
4083 init_unistr(&printer->description, chaine);
4084 init_unistr(&printer->name, ntprinter->info_2->printername);
4086 free_a_printer(&ntprinter,2);
4088 return True;
4091 /****************************************************************************
4092 Free a DEVMODE struct.
4093 ****************************************************************************/
4095 static void free_dev_mode(DEVICEMODE *dev)
4097 if (dev == NULL)
4098 return;
4100 SAFE_FREE(dev->dev_private);
4101 SAFE_FREE(dev);
4105 /****************************************************************************
4106 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4107 should be valid upon entry
4108 ****************************************************************************/
4110 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4112 if ( !devmode || !ntdevmode )
4113 return False;
4115 init_unistr(&devmode->devicename, ntdevmode->devicename);
4117 init_unistr(&devmode->formname, ntdevmode->formname);
4119 devmode->specversion = ntdevmode->specversion;
4120 devmode->driverversion = ntdevmode->driverversion;
4121 devmode->size = ntdevmode->size;
4122 devmode->driverextra = ntdevmode->driverextra;
4123 devmode->fields = ntdevmode->fields;
4125 devmode->orientation = ntdevmode->orientation;
4126 devmode->papersize = ntdevmode->papersize;
4127 devmode->paperlength = ntdevmode->paperlength;
4128 devmode->paperwidth = ntdevmode->paperwidth;
4129 devmode->scale = ntdevmode->scale;
4130 devmode->copies = ntdevmode->copies;
4131 devmode->defaultsource = ntdevmode->defaultsource;
4132 devmode->printquality = ntdevmode->printquality;
4133 devmode->color = ntdevmode->color;
4134 devmode->duplex = ntdevmode->duplex;
4135 devmode->yresolution = ntdevmode->yresolution;
4136 devmode->ttoption = ntdevmode->ttoption;
4137 devmode->collate = ntdevmode->collate;
4138 devmode->icmmethod = ntdevmode->icmmethod;
4139 devmode->icmintent = ntdevmode->icmintent;
4140 devmode->mediatype = ntdevmode->mediatype;
4141 devmode->dithertype = ntdevmode->dithertype;
4143 if (ntdevmode->nt_dev_private != NULL) {
4144 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4145 return False;
4148 return True;
4151 /****************************************************************************
4152 Create a DEVMODE struct. Returns malloced memory.
4153 ****************************************************************************/
4155 DEVICEMODE *construct_dev_mode(const char *servicename)
4157 NT_PRINTER_INFO_LEVEL *printer = NULL;
4158 DEVICEMODE *devmode = NULL;
4160 DEBUG(7,("construct_dev_mode\n"));
4162 DEBUGADD(8,("getting printer characteristics\n"));
4164 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4165 return NULL;
4167 if ( !printer->info_2->devmode ) {
4168 DEBUG(5, ("BONG! There was no device mode!\n"));
4169 goto done;
4172 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4173 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4174 goto done;
4177 ZERO_STRUCTP(devmode);
4179 DEBUGADD(8,("loading DEVICEMODE\n"));
4181 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4182 free_dev_mode( devmode );
4183 devmode = NULL;
4186 done:
4187 free_a_printer(&printer,2);
4189 return devmode;
4192 /********************************************************************
4193 * construct_printer_info_2
4194 * fill a printer_info_2 struct
4195 ********************************************************************/
4197 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4199 int count;
4200 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4202 print_status_struct status;
4204 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4205 return False;
4207 count = print_queue_length(snum, &status);
4209 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4210 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4211 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4212 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4213 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4215 if (*ntprinter->info_2->comment == '\0')
4216 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4217 else
4218 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4220 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4221 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4222 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4223 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4224 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4226 printer->attributes = ntprinter->info_2->attributes;
4228 printer->priority = ntprinter->info_2->priority; /* priority */
4229 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4230 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4231 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4232 printer->status = nt_printq_status(status.status); /* status */
4233 printer->cjobs = count; /* jobs */
4234 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4236 if ( !(printer->devmode = construct_dev_mode(
4237 lp_const_servicename(snum))) )
4238 DEBUG(8, ("Returning NULL Devicemode!\n"));
4240 printer->secdesc = NULL;
4242 if ( ntprinter->info_2->secdesc_buf
4243 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4245 /* don't use talloc_steal() here unless you do a deep steal of all
4246 the SEC_DESC members */
4248 printer->secdesc = dup_sec_desc( talloc_tos(),
4249 ntprinter->info_2->secdesc_buf->sd );
4252 free_a_printer(&ntprinter, 2);
4254 return True;
4257 /********************************************************************
4258 * construct_printer_info_3
4259 * fill a printer_info_3 struct
4260 ********************************************************************/
4262 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4264 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4265 PRINTER_INFO_3 *printer = NULL;
4267 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4268 return False;
4270 *pp_printer = NULL;
4271 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4272 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4273 free_a_printer(&ntprinter, 2);
4274 return False;
4277 ZERO_STRUCTP(printer);
4279 /* These are the components of the SD we are returning. */
4281 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4282 /* don't use talloc_steal() here unless you do a deep steal of all
4283 the SEC_DESC members */
4285 printer->secdesc = dup_sec_desc( talloc_tos(),
4286 ntprinter->info_2->secdesc_buf->sd );
4289 free_a_printer(&ntprinter, 2);
4291 *pp_printer = printer;
4292 return True;
4295 /********************************************************************
4296 * construct_printer_info_4
4297 * fill a printer_info_4 struct
4298 ********************************************************************/
4300 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4302 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4304 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4305 return False;
4307 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4308 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4309 printer->attributes = ntprinter->info_2->attributes;
4311 free_a_printer(&ntprinter, 2);
4312 return True;
4315 /********************************************************************
4316 * construct_printer_info_5
4317 * fill a printer_info_5 struct
4318 ********************************************************************/
4320 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4322 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4324 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4325 return False;
4327 init_unistr(&printer->printername, ntprinter->info_2->printername);
4328 init_unistr(&printer->portname, ntprinter->info_2->portname);
4329 printer->attributes = ntprinter->info_2->attributes;
4331 /* these two are not used by NT+ according to MSDN */
4333 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4334 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4336 free_a_printer(&ntprinter, 2);
4338 return True;
4341 /********************************************************************
4342 * construct_printer_info_6
4343 * fill a printer_info_6 struct
4344 ********************************************************************/
4346 static bool construct_printer_info_6(Printer_entry *print_hnd,
4347 PRINTER_INFO_6 *printer,
4348 int snum)
4350 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4351 int count;
4352 print_status_struct status;
4354 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4355 lp_const_servicename(snum))))
4356 return False;
4358 count = print_queue_length(snum, &status);
4360 printer->status = nt_printq_status(status.status);
4362 free_a_printer(&ntprinter, 2);
4364 return True;
4367 /********************************************************************
4368 * construct_printer_info_7
4369 * fill a printer_info_7 struct
4370 ********************************************************************/
4372 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4374 char *guid_str = NULL;
4375 struct GUID guid;
4377 if (is_printer_published(print_hnd, snum, &guid)) {
4378 if (asprintf(&guid_str, "{%s}",
4379 GUID_string(talloc_tos(), &guid)) == -1) {
4380 return false;
4382 strupper_m(guid_str);
4383 init_unistr(&printer->guid, guid_str);
4384 SAFE_FREE(guid_str);
4385 printer->action = SPOOL_DS_PUBLISH;
4386 } else {
4387 init_unistr(&printer->guid, "");
4388 printer->action = SPOOL_DS_UNPUBLISH;
4391 return True;
4394 /********************************************************************
4395 Spoolss_enumprinters.
4396 ********************************************************************/
4398 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4400 int snum;
4401 int i;
4402 int n_services=lp_numservices();
4403 PRINTER_INFO_1 *printers=NULL;
4404 PRINTER_INFO_1 current_prt;
4405 WERROR result = WERR_OK;
4407 DEBUG(4,("enum_all_printers_info_1\n"));
4409 for (snum=0; snum<n_services; snum++) {
4410 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4411 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4413 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4414 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4415 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4416 *returned=0;
4417 return WERR_NOMEM;
4419 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4421 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4422 (*returned)++;
4427 /* check the required size. */
4428 for (i=0; i<*returned; i++)
4429 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4431 if (*needed > offered) {
4432 result = WERR_INSUFFICIENT_BUFFER;
4433 goto out;
4436 if (!rpcbuf_alloc_size(buffer, *needed)) {
4437 result = WERR_NOMEM;
4438 goto out;
4441 /* fill the buffer with the structures */
4442 for (i=0; i<*returned; i++)
4443 smb_io_printer_info_1("", buffer, &printers[i], 0);
4445 out:
4446 /* clear memory */
4448 SAFE_FREE(printers);
4450 if ( !W_ERROR_IS_OK(result) )
4451 *returned = 0;
4453 return result;
4456 /********************************************************************
4457 enum_all_printers_info_1_local.
4458 *********************************************************************/
4460 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4462 DEBUG(4,("enum_all_printers_info_1_local\n"));
4464 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4467 /********************************************************************
4468 enum_all_printers_info_1_name.
4469 *********************************************************************/
4471 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4473 char *s = name;
4475 DEBUG(4,("enum_all_printers_info_1_name\n"));
4477 if ((name[0] == '\\') && (name[1] == '\\'))
4478 s = name + 2;
4480 if (is_myname_or_ipaddr(s)) {
4481 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4483 else
4484 return WERR_INVALID_NAME;
4487 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4488 /********************************************************************
4489 enum_all_printers_info_1_remote.
4490 *********************************************************************/
4492 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4494 PRINTER_INFO_1 *printer;
4495 fstring printername;
4496 fstring desc;
4497 fstring comment;
4498 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4499 WERROR result = WERR_OK;
4501 /* JFM: currently it's more a place holder than anything else.
4502 * In the spooler world there is a notion of server registration.
4503 * the print servers are registered on the PDC (in the same domain)
4505 * We should have a TDB here. The registration is done thru an
4506 * undocumented RPC call.
4509 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4510 return WERR_NOMEM;
4512 *returned=1;
4514 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4515 slprintf(desc, sizeof(desc)-1,"%s", name);
4516 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4518 init_unistr(&printer->description, desc);
4519 init_unistr(&printer->name, printername);
4520 init_unistr(&printer->comment, comment);
4521 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4523 /* check the required size. */
4524 *needed += spoolss_size_printer_info_1(printer);
4526 if (*needed > offered) {
4527 result = WERR_INSUFFICIENT_BUFFER;
4528 goto out;
4531 if (!rpcbuf_alloc_size(buffer, *needed)) {
4532 result = WERR_NOMEM;
4533 goto out;
4536 /* fill the buffer with the structures */
4537 smb_io_printer_info_1("", buffer, printer, 0);
4539 out:
4540 /* clear memory */
4541 SAFE_FREE(printer);
4543 if ( !W_ERROR_IS_OK(result) )
4544 *returned = 0;
4546 return result;
4549 #endif
4551 /********************************************************************
4552 enum_all_printers_info_1_network.
4553 *********************************************************************/
4555 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4557 char *s = name;
4559 DEBUG(4,("enum_all_printers_info_1_network\n"));
4561 /* If we respond to a enum_printers level 1 on our name with flags
4562 set to PRINTER_ENUM_REMOTE with a list of printers then these
4563 printers incorrectly appear in the APW browse list.
4564 Specifically the printers for the server appear at the workgroup
4565 level where all the other servers in the domain are
4566 listed. Windows responds to this call with a
4567 WERR_CAN_NOT_COMPLETE so we should do the same. */
4569 if (name[0] == '\\' && name[1] == '\\')
4570 s = name + 2;
4572 if (is_myname_or_ipaddr(s))
4573 return WERR_CAN_NOT_COMPLETE;
4575 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4578 /********************************************************************
4579 * api_spoolss_enumprinters
4581 * called from api_spoolss_enumprinters (see this to understand)
4582 ********************************************************************/
4584 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4586 int snum;
4587 int i;
4588 int n_services=lp_numservices();
4589 PRINTER_INFO_2 *printers=NULL;
4590 PRINTER_INFO_2 current_prt;
4591 WERROR result = WERR_OK;
4593 *returned = 0;
4595 for (snum=0; snum<n_services; snum++) {
4596 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4597 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4599 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4600 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4601 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4602 *returned = 0;
4603 return WERR_NOMEM;
4606 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4608 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4610 (*returned)++;
4615 /* check the required size. */
4616 for (i=0; i<*returned; i++)
4617 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4619 if (*needed > offered) {
4620 result = WERR_INSUFFICIENT_BUFFER;
4621 goto out;
4624 if (!rpcbuf_alloc_size(buffer, *needed)) {
4625 result = WERR_NOMEM;
4626 goto out;
4629 /* fill the buffer with the structures */
4630 for (i=0; i<*returned; i++)
4631 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4633 out:
4634 /* clear memory */
4636 for (i=0; i<*returned; i++)
4637 free_devmode(printers[i].devmode);
4639 SAFE_FREE(printers);
4641 if ( !W_ERROR_IS_OK(result) )
4642 *returned = 0;
4644 return result;
4647 /********************************************************************
4648 * handle enumeration of printers at level 1
4649 ********************************************************************/
4651 static WERROR enumprinters_level1( uint32 flags, fstring name,
4652 RPC_BUFFER *buffer, uint32 offered,
4653 uint32 *needed, uint32 *returned)
4655 /* Not all the flags are equals */
4657 if (flags & PRINTER_ENUM_LOCAL)
4658 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4660 if (flags & PRINTER_ENUM_NAME)
4661 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4663 #if 0 /* JERRY - disabled for now */
4664 if (flags & PRINTER_ENUM_REMOTE)
4665 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4666 #endif
4668 if (flags & PRINTER_ENUM_NETWORK)
4669 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4671 return WERR_OK; /* NT4sp5 does that */
4674 /********************************************************************
4675 * handle enumeration of printers at level 2
4676 ********************************************************************/
4678 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4679 RPC_BUFFER *buffer, uint32 offered,
4680 uint32 *needed, uint32 *returned)
4682 if (flags & PRINTER_ENUM_LOCAL) {
4683 return enum_all_printers_info_2(buffer, offered, needed, returned);
4686 if (flags & PRINTER_ENUM_NAME) {
4687 if (is_myname_or_ipaddr(canon_servername(servername)))
4688 return enum_all_printers_info_2(buffer, offered, needed, returned);
4689 else
4690 return WERR_INVALID_NAME;
4693 if (flags & PRINTER_ENUM_REMOTE)
4694 return WERR_UNKNOWN_LEVEL;
4696 return WERR_OK;
4699 /********************************************************************
4700 * handle enumeration of printers at level 5
4701 ********************************************************************/
4703 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4704 RPC_BUFFER *buffer, uint32 offered,
4705 uint32 *needed, uint32 *returned)
4707 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4708 return WERR_OK;
4711 /********************************************************************
4712 * api_spoolss_enumprinters
4714 * called from api_spoolss_enumprinters (see this to understand)
4715 ********************************************************************/
4717 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4719 uint32 flags = q_u->flags;
4720 UNISTR2 *servername = &q_u->servername;
4721 uint32 level = q_u->level;
4722 RPC_BUFFER *buffer = NULL;
4723 uint32 offered = q_u->offered;
4724 uint32 *needed = &r_u->needed;
4725 uint32 *returned = &r_u->returned;
4727 fstring name;
4729 /* that's an [in out] buffer */
4731 if (!q_u->buffer && (offered!=0)) {
4732 return WERR_INVALID_PARAM;
4735 rpcbuf_move(q_u->buffer, &r_u->buffer);
4736 buffer = r_u->buffer;
4738 DEBUG(4,("_spoolss_enumprinters\n"));
4740 *needed=0;
4741 *returned=0;
4744 * Level 1:
4745 * flags==PRINTER_ENUM_NAME
4746 * if name=="" then enumerates all printers
4747 * if name!="" then enumerate the printer
4748 * flags==PRINTER_ENUM_REMOTE
4749 * name is NULL, enumerate printers
4750 * Level 2: name!="" enumerates printers, name can't be NULL
4751 * Level 3: doesn't exist
4752 * Level 4: does a local registry lookup
4753 * Level 5: same as Level 2
4756 unistr2_to_ascii(name, servername, sizeof(name));
4757 strupper_m(name);
4759 switch (level) {
4760 case 1:
4761 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4762 case 2:
4763 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4764 case 5:
4765 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4766 case 3:
4767 case 4:
4768 break;
4770 return WERR_UNKNOWN_LEVEL;
4773 /****************************************************************************
4774 ****************************************************************************/
4776 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4778 PRINTER_INFO_0 *printer=NULL;
4779 WERROR result = WERR_OK;
4781 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4782 return WERR_NOMEM;
4784 construct_printer_info_0(print_hnd, printer, snum);
4786 /* check the required size. */
4787 *needed += spoolss_size_printer_info_0(printer);
4789 if (*needed > offered) {
4790 result = WERR_INSUFFICIENT_BUFFER;
4791 goto out;
4794 if (!rpcbuf_alloc_size(buffer, *needed)) {
4795 result = WERR_NOMEM;
4796 goto out;
4799 /* fill the buffer with the structures */
4800 smb_io_printer_info_0("", buffer, printer, 0);
4802 out:
4803 /* clear memory */
4805 SAFE_FREE(printer);
4807 return result;
4810 /****************************************************************************
4811 ****************************************************************************/
4813 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4815 PRINTER_INFO_1 *printer=NULL;
4816 WERROR result = WERR_OK;
4818 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4819 return WERR_NOMEM;
4821 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4823 /* check the required size. */
4824 *needed += spoolss_size_printer_info_1(printer);
4826 if (*needed > offered) {
4827 result = WERR_INSUFFICIENT_BUFFER;
4828 goto out;
4831 if (!rpcbuf_alloc_size(buffer, *needed)) {
4832 result = WERR_NOMEM;
4833 goto out;
4836 /* fill the buffer with the structures */
4837 smb_io_printer_info_1("", buffer, printer, 0);
4839 out:
4840 /* clear memory */
4841 SAFE_FREE(printer);
4843 return result;
4846 /****************************************************************************
4847 ****************************************************************************/
4849 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4851 PRINTER_INFO_2 *printer=NULL;
4852 WERROR result = WERR_OK;
4854 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4855 return WERR_NOMEM;
4857 construct_printer_info_2(print_hnd, printer, snum);
4859 /* check the required size. */
4860 *needed += spoolss_size_printer_info_2(printer);
4862 if (*needed > offered) {
4863 result = WERR_INSUFFICIENT_BUFFER;
4864 goto out;
4867 if (!rpcbuf_alloc_size(buffer, *needed)) {
4868 result = WERR_NOMEM;
4869 goto out;
4872 /* fill the buffer with the structures */
4873 if (!smb_io_printer_info_2("", buffer, printer, 0))
4874 result = WERR_NOMEM;
4876 out:
4877 /* clear memory */
4878 free_printer_info_2(printer);
4880 return result;
4883 /****************************************************************************
4884 ****************************************************************************/
4886 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4888 PRINTER_INFO_3 *printer=NULL;
4889 WERROR result = WERR_OK;
4891 if (!construct_printer_info_3(print_hnd, &printer, snum))
4892 return WERR_NOMEM;
4894 /* check the required size. */
4895 *needed += spoolss_size_printer_info_3(printer);
4897 if (*needed > offered) {
4898 result = WERR_INSUFFICIENT_BUFFER;
4899 goto out;
4902 if (!rpcbuf_alloc_size(buffer, *needed)) {
4903 result = WERR_NOMEM;
4904 goto out;
4907 /* fill the buffer with the structures */
4908 smb_io_printer_info_3("", buffer, printer, 0);
4910 out:
4911 /* clear memory */
4912 free_printer_info_3(printer);
4914 return result;
4917 /****************************************************************************
4918 ****************************************************************************/
4920 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4922 PRINTER_INFO_4 *printer=NULL;
4923 WERROR result = WERR_OK;
4925 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4926 return WERR_NOMEM;
4928 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4929 SAFE_FREE(printer);
4930 return WERR_NOMEM;
4933 /* check the required size. */
4934 *needed += spoolss_size_printer_info_4(printer);
4936 if (*needed > offered) {
4937 result = WERR_INSUFFICIENT_BUFFER;
4938 goto out;
4941 if (!rpcbuf_alloc_size(buffer, *needed)) {
4942 result = WERR_NOMEM;
4943 goto out;
4946 /* fill the buffer with the structures */
4947 smb_io_printer_info_4("", buffer, printer, 0);
4949 out:
4950 /* clear memory */
4951 free_printer_info_4(printer);
4953 return result;
4956 /****************************************************************************
4957 ****************************************************************************/
4959 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4961 PRINTER_INFO_5 *printer=NULL;
4962 WERROR result = WERR_OK;
4964 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4965 return WERR_NOMEM;
4967 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4968 free_printer_info_5(printer);
4969 return WERR_NOMEM;
4972 /* check the required size. */
4973 *needed += spoolss_size_printer_info_5(printer);
4975 if (*needed > offered) {
4976 result = WERR_INSUFFICIENT_BUFFER;
4977 goto out;
4980 if (!rpcbuf_alloc_size(buffer, *needed)) {
4981 result = WERR_NOMEM;
4982 goto out;
4985 /* fill the buffer with the structures */
4986 smb_io_printer_info_5("", buffer, printer, 0);
4988 out:
4989 /* clear memory */
4990 free_printer_info_5(printer);
4992 return result;
4995 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4996 int snum,
4997 RPC_BUFFER *buffer, uint32 offered,
4998 uint32 *needed)
5000 PRINTER_INFO_6 *printer;
5001 WERROR result = WERR_OK;
5003 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5004 return WERR_NOMEM;
5007 if (!construct_printer_info_6(print_hnd, printer, snum)) {
5008 free_printer_info_6(printer);
5009 return WERR_NOMEM;
5012 /* check the required size. */
5013 *needed += spoolss_size_printer_info_6(printer);
5015 if (*needed > offered) {
5016 result = WERR_INSUFFICIENT_BUFFER;
5017 goto out;
5020 if (!rpcbuf_alloc_size(buffer, *needed)) {
5021 result = WERR_NOMEM;
5022 goto out;
5025 /* fill the buffer with the structures */
5026 smb_io_printer_info_6("", buffer, printer, 0);
5028 out:
5029 /* clear memory */
5030 free_printer_info_6(printer);
5032 return result;
5035 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5037 PRINTER_INFO_7 *printer=NULL;
5038 WERROR result = WERR_OK;
5040 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5041 return WERR_NOMEM;
5043 if (!construct_printer_info_7(print_hnd, printer, snum)) {
5044 result = WERR_NOMEM;
5045 goto out;
5048 /* check the required size. */
5049 *needed += spoolss_size_printer_info_7(printer);
5051 if (*needed > offered) {
5052 result = WERR_INSUFFICIENT_BUFFER;
5053 goto out;
5056 if (!rpcbuf_alloc_size(buffer, *needed)) {
5057 result = WERR_NOMEM;
5058 goto out;
5062 /* fill the buffer with the structures */
5063 smb_io_printer_info_7("", buffer, printer, 0);
5065 out:
5066 /* clear memory */
5067 free_printer_info_7(printer);
5069 return result;
5072 /****************************************************************************
5073 ****************************************************************************/
5075 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5077 POLICY_HND *handle = &q_u->handle;
5078 uint32 level = q_u->level;
5079 RPC_BUFFER *buffer = NULL;
5080 uint32 offered = q_u->offered;
5081 uint32 *needed = &r_u->needed;
5082 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5084 int snum;
5086 /* that's an [in out] buffer */
5088 if (!q_u->buffer && (offered!=0)) {
5089 return WERR_INVALID_PARAM;
5092 rpcbuf_move(q_u->buffer, &r_u->buffer);
5093 buffer = r_u->buffer;
5095 *needed=0;
5097 if (!get_printer_snum(p, handle, &snum, NULL))
5098 return WERR_BADFID;
5100 switch (level) {
5101 case 0:
5102 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5103 case 1:
5104 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5105 case 2:
5106 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5107 case 3:
5108 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5109 case 4:
5110 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5111 case 5:
5112 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5113 case 6:
5114 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5115 case 7:
5116 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5118 return WERR_UNKNOWN_LEVEL;
5121 /********************************************************************
5122 * fill a DRIVER_INFO_1 struct
5123 ********************************************************************/
5125 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5127 init_unistr( &info->name, driver.info_3->name);
5130 /********************************************************************
5131 * construct_printer_driver_info_1
5132 ********************************************************************/
5134 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5136 NT_PRINTER_INFO_LEVEL *printer = NULL;
5137 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5139 ZERO_STRUCT(driver);
5141 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5142 return WERR_INVALID_PRINTER_NAME;
5144 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5145 free_a_printer(&printer, 2);
5146 return WERR_UNKNOWN_PRINTER_DRIVER;
5149 fill_printer_driver_info_1(info, driver, servername, architecture);
5151 free_a_printer(&printer,2);
5153 return WERR_OK;
5156 /********************************************************************
5157 * construct_printer_driver_info_2
5158 * fill a printer_info_2 struct
5159 ********************************************************************/
5161 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5163 TALLOC_CTX *ctx = talloc_tos();
5164 char *temp = NULL;
5165 const char *cservername = canon_servername(servername);
5167 info->version=driver.info_3->cversion;
5169 init_unistr( &info->name, driver.info_3->name );
5170 init_unistr( &info->architecture, driver.info_3->environment );
5172 if (strlen(driver.info_3->driverpath)) {
5173 temp = talloc_asprintf(ctx,
5174 "\\\\%s%s",
5175 cservername,
5176 driver.info_3->driverpath);
5177 init_unistr( &info->driverpath, temp );
5178 } else {
5179 init_unistr( &info->driverpath, "" );
5182 TALLOC_FREE(temp);
5183 if (strlen(driver.info_3->datafile)) {
5184 temp = talloc_asprintf(ctx,
5185 "\\\\%s%s",
5186 cservername,
5187 driver.info_3->datafile);
5188 init_unistr( &info->datafile, temp );
5189 } else
5190 init_unistr( &info->datafile, "" );
5192 TALLOC_FREE(temp);
5193 if (strlen(driver.info_3->configfile)) {
5194 temp = talloc_asprintf(ctx,
5195 "\\\\%s%s",
5196 cservername,
5197 driver.info_3->configfile);
5198 init_unistr( &info->configfile, temp );
5199 } else
5200 init_unistr( &info->configfile, "" );
5203 /********************************************************************
5204 * construct_printer_driver_info_2
5205 * fill a printer_info_2 struct
5206 ********************************************************************/
5208 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5210 NT_PRINTER_INFO_LEVEL *printer = NULL;
5211 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5213 ZERO_STRUCT(printer);
5214 ZERO_STRUCT(driver);
5216 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5217 return WERR_INVALID_PRINTER_NAME;
5219 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5220 free_a_printer(&printer, 2);
5221 return WERR_UNKNOWN_PRINTER_DRIVER;
5224 fill_printer_driver_info_2(info, driver, servername);
5226 free_a_printer(&printer,2);
5228 return WERR_OK;
5231 /********************************************************************
5232 * copy a strings array and convert to UNICODE
5234 * convert an array of ascii string to a UNICODE string
5235 ********************************************************************/
5237 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5239 int i=0;
5240 int j=0;
5241 const char *v;
5242 char *line = NULL;
5243 TALLOC_CTX *ctx = talloc_tos();
5245 DEBUG(6,("init_unistr_array\n"));
5246 *uni_array=NULL;
5248 while (true) {
5249 if ( !char_array ) {
5250 v = "";
5251 } else {
5252 v = char_array[i];
5253 if (!v)
5254 v = ""; /* hack to handle null lists */
5257 /* hack to allow this to be used in places other than when generating
5258 the list of dependent files */
5260 TALLOC_FREE(line);
5261 if ( servername ) {
5262 line = talloc_asprintf(ctx,
5263 "\\\\%s%s",
5264 canon_servername(servername),
5266 } else {
5267 line = talloc_strdup(ctx, v);
5270 if (!line) {
5271 SAFE_FREE(*uni_array);
5272 return 0;
5274 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5276 /* add one extra unit16 for the second terminating NULL */
5278 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5279 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5280 return 0;
5283 if ( !strlen(v) )
5284 break;
5286 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5287 i++;
5290 if (*uni_array) {
5291 /* special case for ""; we need to add both NULL's here */
5292 if (!j)
5293 (*uni_array)[j++]=0x0000;
5294 (*uni_array)[j]=0x0000;
5297 DEBUGADD(6,("last one:done\n"));
5299 /* return size of array in uint16's */
5301 return j+1;
5304 /********************************************************************
5305 * construct_printer_info_3
5306 * fill a printer_info_3 struct
5307 ********************************************************************/
5309 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5311 char *temp = NULL;
5312 TALLOC_CTX *ctx = talloc_tos();
5313 const char *cservername = canon_servername(servername);
5315 ZERO_STRUCTP(info);
5317 info->version=driver.info_3->cversion;
5319 init_unistr( &info->name, driver.info_3->name );
5320 init_unistr( &info->architecture, driver.info_3->environment );
5322 if (strlen(driver.info_3->driverpath)) {
5323 temp = talloc_asprintf(ctx,
5324 "\\\\%s%s",
5325 cservername,
5326 driver.info_3->driverpath);
5327 init_unistr( &info->driverpath, temp );
5328 } else
5329 init_unistr( &info->driverpath, "" );
5331 TALLOC_FREE(temp);
5332 if (strlen(driver.info_3->datafile)) {
5333 temp = talloc_asprintf(ctx,
5334 "\\\\%s%s",
5335 cservername,
5336 driver.info_3->datafile);
5337 init_unistr( &info->datafile, temp );
5338 } else
5339 init_unistr( &info->datafile, "" );
5341 TALLOC_FREE(temp);
5342 if (strlen(driver.info_3->configfile)) {
5343 temp = talloc_asprintf(ctx,
5344 "\\\\%s%s",
5345 cservername,
5346 driver.info_3->configfile);
5347 init_unistr( &info->configfile, temp );
5348 } else
5349 init_unistr( &info->configfile, "" );
5351 TALLOC_FREE(temp);
5352 if (strlen(driver.info_3->helpfile)) {
5353 temp = talloc_asprintf(ctx,
5354 "\\\\%s%s",
5355 cservername,
5356 driver.info_3->helpfile);
5357 init_unistr( &info->helpfile, temp );
5358 } else
5359 init_unistr( &info->helpfile, "" );
5361 TALLOC_FREE(temp);
5362 init_unistr( &info->monitorname, driver.info_3->monitorname );
5363 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5365 info->dependentfiles=NULL;
5366 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5369 /********************************************************************
5370 * construct_printer_info_3
5371 * fill a printer_info_3 struct
5372 ********************************************************************/
5374 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5376 NT_PRINTER_INFO_LEVEL *printer = NULL;
5377 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5378 WERROR status;
5379 ZERO_STRUCT(driver);
5381 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5382 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5383 if (!W_ERROR_IS_OK(status))
5384 return WERR_INVALID_PRINTER_NAME;
5386 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5387 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5389 #if 0 /* JERRY */
5392 * I put this code in during testing. Helpful when commenting out the
5393 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5394 * as win2k always queries the driver using an infor level of 6.
5395 * I've left it in (but ifdef'd out) because I'll probably
5396 * use it in experimentation again in the future. --jerry 22/01/2002
5399 if (!W_ERROR_IS_OK(status)) {
5401 * Is this a W2k client ?
5403 if (version == 3) {
5404 /* Yes - try again with a WinNT driver. */
5405 version = 2;
5406 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5407 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5409 #endif
5411 if (!W_ERROR_IS_OK(status)) {
5412 free_a_printer(&printer,2);
5413 return WERR_UNKNOWN_PRINTER_DRIVER;
5416 #if 0 /* JERRY */
5418 #endif
5421 fill_printer_driver_info_3(info, driver, servername);
5423 free_a_printer(&printer,2);
5425 return WERR_OK;
5428 /********************************************************************
5429 * construct_printer_info_6
5430 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5431 ********************************************************************/
5433 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5435 char *temp = NULL;
5436 fstring nullstr;
5437 TALLOC_CTX *ctx = talloc_tos();
5438 const char *cservername = canon_servername(servername);
5440 ZERO_STRUCTP(info);
5441 memset(&nullstr, '\0', sizeof(fstring));
5443 info->version=driver.info_3->cversion;
5445 init_unistr( &info->name, driver.info_3->name );
5446 init_unistr( &info->architecture, driver.info_3->environment );
5448 if (strlen(driver.info_3->driverpath)) {
5449 temp = talloc_asprintf(ctx,
5450 "\\\\%s%s",
5451 cservername,
5452 driver.info_3->driverpath);
5453 init_unistr( &info->driverpath, temp );
5454 } else
5455 init_unistr( &info->driverpath, "" );
5457 TALLOC_FREE(temp);
5458 if (strlen(driver.info_3->datafile)) {
5459 temp = talloc_asprintf(ctx,
5460 "\\\\%s%s",
5461 cservername,
5462 driver.info_3->datafile);
5463 init_unistr( &info->datafile, temp );
5464 } else
5465 init_unistr( &info->datafile, "" );
5467 TALLOC_FREE(temp);
5468 if (strlen(driver.info_3->configfile)) {
5469 temp = talloc_asprintf(ctx,
5470 "\\\\%s%s",
5471 cservername,
5472 driver.info_3->configfile);
5473 init_unistr( &info->configfile, temp );
5474 } else
5475 init_unistr( &info->configfile, "" );
5477 TALLOC_FREE(temp);
5478 if (strlen(driver.info_3->helpfile)) {
5479 temp = talloc_asprintf(ctx,
5480 "\\\\%s%s",
5481 cservername,
5482 driver.info_3->helpfile);
5483 init_unistr( &info->helpfile, temp );
5484 } else
5485 init_unistr( &info->helpfile, "" );
5487 TALLOC_FREE(temp);
5488 init_unistr( &info->monitorname, driver.info_3->monitorname );
5489 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5491 info->dependentfiles = NULL;
5492 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5494 info->previousdrivernames=NULL;
5495 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5497 info->driver_date=0;
5499 info->padding=0;
5500 info->driver_version_low=0;
5501 info->driver_version_high=0;
5503 init_unistr( &info->mfgname, "");
5504 init_unistr( &info->oem_url, "");
5505 init_unistr( &info->hardware_id, "");
5506 init_unistr( &info->provider, "");
5509 /********************************************************************
5510 * construct_printer_info_6
5511 * fill a printer_info_6 struct
5512 ********************************************************************/
5514 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5515 const char *servername, fstring architecture, uint32 version)
5517 NT_PRINTER_INFO_LEVEL *printer = NULL;
5518 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5519 WERROR status;
5521 ZERO_STRUCT(driver);
5523 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5525 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5527 if (!W_ERROR_IS_OK(status))
5528 return WERR_INVALID_PRINTER_NAME;
5530 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5532 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5534 if (!W_ERROR_IS_OK(status))
5537 * Is this a W2k client ?
5540 if (version < 3) {
5541 free_a_printer(&printer,2);
5542 return WERR_UNKNOWN_PRINTER_DRIVER;
5545 /* Yes - try again with a WinNT driver. */
5546 version = 2;
5547 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5548 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5549 if (!W_ERROR_IS_OK(status)) {
5550 free_a_printer(&printer,2);
5551 return WERR_UNKNOWN_PRINTER_DRIVER;
5555 fill_printer_driver_info_6(info, driver, servername);
5557 free_a_printer(&printer,2);
5558 free_a_printer_driver(driver, 3);
5560 return WERR_OK;
5563 /****************************************************************************
5564 ****************************************************************************/
5566 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5568 SAFE_FREE(info->dependentfiles);
5571 /****************************************************************************
5572 ****************************************************************************/
5574 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5576 SAFE_FREE(info->dependentfiles);
5579 /****************************************************************************
5580 ****************************************************************************/
5582 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5584 DRIVER_INFO_1 *info=NULL;
5585 WERROR result;
5587 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5588 return WERR_NOMEM;
5590 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5591 if (!W_ERROR_IS_OK(result))
5592 goto out;
5594 /* check the required size. */
5595 *needed += spoolss_size_printer_driver_info_1(info);
5597 if (*needed > offered) {
5598 result = WERR_INSUFFICIENT_BUFFER;
5599 goto out;
5602 if (!rpcbuf_alloc_size(buffer, *needed)) {
5603 result = WERR_NOMEM;
5604 goto out;
5607 /* fill the buffer with the structures */
5608 smb_io_printer_driver_info_1("", buffer, info, 0);
5610 out:
5611 /* clear memory */
5612 SAFE_FREE(info);
5614 return result;
5617 /****************************************************************************
5618 ****************************************************************************/
5620 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5622 DRIVER_INFO_2 *info=NULL;
5623 WERROR result;
5625 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5626 return WERR_NOMEM;
5628 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5629 if (!W_ERROR_IS_OK(result))
5630 goto out;
5632 /* check the required size. */
5633 *needed += spoolss_size_printer_driver_info_2(info);
5635 if (*needed > offered) {
5636 result = WERR_INSUFFICIENT_BUFFER;
5637 goto out;
5640 if (!rpcbuf_alloc_size(buffer, *needed)) {
5641 result = WERR_NOMEM;
5642 goto out;
5645 /* fill the buffer with the structures */
5646 smb_io_printer_driver_info_2("", buffer, info, 0);
5648 out:
5649 /* clear memory */
5650 SAFE_FREE(info);
5652 return result;
5655 /****************************************************************************
5656 ****************************************************************************/
5658 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5660 DRIVER_INFO_3 info;
5661 WERROR result;
5663 ZERO_STRUCT(info);
5665 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5666 if (!W_ERROR_IS_OK(result))
5667 goto out;
5669 /* check the required size. */
5670 *needed += spoolss_size_printer_driver_info_3(&info);
5672 if (*needed > offered) {
5673 result = WERR_INSUFFICIENT_BUFFER;
5674 goto out;
5677 if (!rpcbuf_alloc_size(buffer, *needed)) {
5678 result = WERR_NOMEM;
5679 goto out;
5682 /* fill the buffer with the structures */
5683 smb_io_printer_driver_info_3("", buffer, &info, 0);
5685 out:
5686 free_printer_driver_info_3(&info);
5688 return result;
5691 /****************************************************************************
5692 ****************************************************************************/
5694 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5696 DRIVER_INFO_6 info;
5697 WERROR result;
5699 ZERO_STRUCT(info);
5701 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5702 if (!W_ERROR_IS_OK(result))
5703 goto out;
5705 /* check the required size. */
5706 *needed += spoolss_size_printer_driver_info_6(&info);
5708 if (*needed > offered) {
5709 result = WERR_INSUFFICIENT_BUFFER;
5710 goto out;
5713 if (!rpcbuf_alloc_size(buffer, *needed)) {
5714 result = WERR_NOMEM;
5715 goto out;
5718 /* fill the buffer with the structures */
5719 smb_io_printer_driver_info_6("", buffer, &info, 0);
5721 out:
5722 free_printer_driver_info_6(&info);
5724 return result;
5727 /****************************************************************************
5728 ****************************************************************************/
5730 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5732 POLICY_HND *handle = &q_u->handle;
5733 UNISTR2 *uni_arch = &q_u->architecture;
5734 uint32 level = q_u->level;
5735 uint32 clientmajorversion = q_u->clientmajorversion;
5736 RPC_BUFFER *buffer = NULL;
5737 uint32 offered = q_u->offered;
5738 uint32 *needed = &r_u->needed;
5739 uint32 *servermajorversion = &r_u->servermajorversion;
5740 uint32 *serverminorversion = &r_u->serverminorversion;
5741 Printer_entry *printer;
5743 fstring servername;
5744 fstring architecture;
5745 int snum;
5747 /* that's an [in out] buffer */
5749 if (!q_u->buffer && (offered!=0)) {
5750 return WERR_INVALID_PARAM;
5753 rpcbuf_move(q_u->buffer, &r_u->buffer);
5754 buffer = r_u->buffer;
5756 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5758 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5759 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5760 return WERR_INVALID_PRINTER_NAME;
5763 *needed = 0;
5764 *servermajorversion = 0;
5765 *serverminorversion = 0;
5767 fstrcpy(servername, get_server_name( printer ));
5768 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5770 if (!get_printer_snum(p, handle, &snum, NULL))
5771 return WERR_BADFID;
5773 switch (level) {
5774 case 1:
5775 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5776 case 2:
5777 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5778 case 3:
5779 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5780 case 6:
5781 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5782 #if 0 /* JERRY */
5783 case 101:
5784 /* apparently this call is the equivalent of
5785 EnumPrinterDataEx() for the DsDriver key */
5786 break;
5787 #endif
5790 return WERR_UNKNOWN_LEVEL;
5793 /****************************************************************************
5794 ****************************************************************************/
5796 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5798 POLICY_HND *handle = &q_u->handle;
5800 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5802 if (!Printer) {
5803 DEBUG(3,("Error in startpageprinter printer handle\n"));
5804 return WERR_BADFID;
5807 Printer->page_started=True;
5808 return WERR_OK;
5811 /****************************************************************************
5812 ****************************************************************************/
5814 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5816 POLICY_HND *handle = &q_u->handle;
5817 int snum;
5819 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5821 if (!Printer) {
5822 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5823 return WERR_BADFID;
5826 if (!get_printer_snum(p, handle, &snum, NULL))
5827 return WERR_BADFID;
5829 Printer->page_started=False;
5830 print_job_endpage(snum, Printer->jobid);
5832 return WERR_OK;
5835 /********************************************************************
5836 * api_spoolss_getprinter
5837 * called from the spoolss dispatcher
5839 ********************************************************************/
5841 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5843 POLICY_HND *handle = &q_u->handle;
5844 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5845 uint32 *jobid = &r_u->jobid;
5846 TALLOC_CTX *ctx = p->mem_ctx;
5847 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5848 int snum;
5849 char *jobname = NULL;
5850 fstring datatype;
5851 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5853 if (!Printer) {
5854 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5855 return WERR_BADFID;
5859 * a nice thing with NT is it doesn't listen to what you tell it.
5860 * when asked to send _only_ RAW datas, it tries to send datas
5861 * in EMF format.
5863 * So I add checks like in NT Server ...
5866 if (info_1->p_datatype != 0) {
5867 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5868 if (strcmp(datatype, "RAW") != 0) {
5869 (*jobid)=0;
5870 return WERR_INVALID_DATATYPE;
5874 /* get the share number of the printer */
5875 if (!get_printer_snum(p, handle, &snum, NULL)) {
5876 return WERR_BADFID;
5879 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5881 Printer->jobid = print_job_start(p->server_info, snum, jobname,
5882 Printer->nt_devmode);
5884 /* An error occured in print_job_start() so return an appropriate
5885 NT error code. */
5887 if (Printer->jobid == -1) {
5888 return map_werror_from_unix(errno);
5891 Printer->document_started=True;
5892 (*jobid) = Printer->jobid;
5894 return WERR_OK;
5897 /********************************************************************
5898 * api_spoolss_getprinter
5899 * called from the spoolss dispatcher
5901 ********************************************************************/
5903 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5905 POLICY_HND *handle = &q_u->handle;
5907 return _spoolss_enddocprinter_internal(p, handle);
5910 /****************************************************************************
5911 ****************************************************************************/
5913 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5915 POLICY_HND *handle = &q_u->handle;
5916 uint32 buffer_size = q_u->buffer_size;
5917 uint8 *buffer = q_u->buffer;
5918 uint32 *buffer_written = &q_u->buffer_size2;
5919 int snum;
5920 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5922 if (!Printer) {
5923 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5924 r_u->buffer_written = q_u->buffer_size2;
5925 return WERR_BADFID;
5928 if (!get_printer_snum(p, handle, &snum, NULL))
5929 return WERR_BADFID;
5931 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5932 (SMB_OFF_T)-1, (size_t)buffer_size);
5933 if (*buffer_written == (uint32)-1) {
5934 r_u->buffer_written = 0;
5935 if (errno == ENOSPC)
5936 return WERR_NO_SPOOL_SPACE;
5937 else
5938 return WERR_ACCESS_DENIED;
5941 r_u->buffer_written = q_u->buffer_size2;
5943 return WERR_OK;
5946 /********************************************************************
5947 * api_spoolss_getprinter
5948 * called from the spoolss dispatcher
5950 ********************************************************************/
5952 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5953 pipes_struct *p)
5955 int snum;
5956 WERROR errcode = WERR_BADFUNC;
5957 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5959 if (!Printer) {
5960 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5961 return WERR_BADFID;
5964 if (!get_printer_snum(p, handle, &snum, NULL))
5965 return WERR_BADFID;
5967 switch (command) {
5968 case PRINTER_CONTROL_PAUSE:
5969 if (print_queue_pause(p->server_info, snum, &errcode)) {
5970 errcode = WERR_OK;
5972 break;
5973 case PRINTER_CONTROL_RESUME:
5974 case PRINTER_CONTROL_UNPAUSE:
5975 if (print_queue_resume(p->server_info, snum, &errcode)) {
5976 errcode = WERR_OK;
5978 break;
5979 case PRINTER_CONTROL_PURGE:
5980 if (print_queue_purge(p->server_info, snum, &errcode)) {
5981 errcode = WERR_OK;
5983 break;
5984 default:
5985 return WERR_UNKNOWN_LEVEL;
5988 return errcode;
5991 /********************************************************************
5992 * api_spoolss_abortprinter
5993 * From MSDN: "Deletes printer's spool file if printer is configured
5994 * for spooling"
5995 ********************************************************************/
5997 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5999 POLICY_HND *handle = &q_u->handle;
6000 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6001 int snum;
6002 WERROR errcode = WERR_OK;
6004 if (!Printer) {
6005 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
6006 return WERR_BADFID;
6009 if (!get_printer_snum(p, handle, &snum, NULL))
6010 return WERR_BADFID;
6012 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6014 return errcode;
6017 /********************************************************************
6018 * called by spoolss_api_setprinter
6019 * when updating a printer description
6020 ********************************************************************/
6022 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6023 const SPOOL_PRINTER_INFO_LEVEL *info,
6024 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6026 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6027 WERROR result;
6028 int snum;
6030 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6032 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6033 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6034 OUR_HANDLE(handle)));
6036 result = WERR_BADFID;
6037 goto done;
6040 if (!secdesc_ctr) {
6041 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6042 result = WERR_INVALID_PARAM;
6043 goto done;
6046 /* Check the user has permissions to change the security
6047 descriptor. By experimentation with two NT machines, the user
6048 requires Full Access to the printer to change security
6049 information. */
6051 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6052 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6053 result = WERR_ACCESS_DENIED;
6054 goto done;
6057 /* NT seems to like setting the security descriptor even though
6058 nothing may have actually changed. */
6060 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6061 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6062 result = WERR_BADFID;
6063 goto done;
6066 if (DEBUGLEVEL >= 10) {
6067 SEC_ACL *the_acl;
6068 int i;
6070 the_acl = old_secdesc_ctr->sd->dacl;
6071 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6072 PRINTERNAME(snum), the_acl->num_aces));
6074 for (i = 0; i < the_acl->num_aces; i++) {
6075 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6076 &the_acl->aces[i].trustee),
6077 the_acl->aces[i].access_mask));
6080 the_acl = secdesc_ctr->sd->dacl;
6082 if (the_acl) {
6083 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6084 PRINTERNAME(snum), the_acl->num_aces));
6086 for (i = 0; i < the_acl->num_aces; i++) {
6087 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6088 &the_acl->aces[i].trustee),
6089 the_acl->aces[i].access_mask));
6091 } else {
6092 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6096 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6097 if (!new_secdesc_ctr) {
6098 result = WERR_NOMEM;
6099 goto done;
6102 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6103 result = WERR_OK;
6104 goto done;
6107 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6109 done:
6111 return result;
6114 /********************************************************************
6115 Canonicalize printer info from a client
6117 ATTN: It does not matter what we set the servername to hear
6118 since we do the necessary work in get_a_printer() to set it to
6119 the correct value based on what the client sent in the
6120 _spoolss_open_printer_ex().
6121 ********************************************************************/
6123 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6125 fstring printername;
6126 const char *p;
6128 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6129 "portname=%s drivername=%s comment=%s location=%s\n",
6130 info->servername, info->printername, info->sharename,
6131 info->portname, info->drivername, info->comment, info->location));
6133 /* we force some elements to "correct" values */
6134 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6135 fstrcpy(info->sharename, lp_servicename(snum));
6137 /* check to see if we allow printername != sharename */
6139 if ( lp_force_printername(snum) ) {
6140 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6141 global_myname(), info->sharename );
6142 } else {
6144 /* make sure printername is in \\server\printername format */
6146 fstrcpy( printername, info->printername );
6147 p = printername;
6148 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6149 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6150 p++;
6153 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6154 global_myname(), p );
6157 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6158 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6162 return True;
6165 /****************************************************************************
6166 ****************************************************************************/
6168 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6170 char *cmd = lp_addport_cmd();
6171 char *command = NULL;
6172 int ret;
6173 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6174 bool is_print_op = False;
6176 if ( !*cmd ) {
6177 return WERR_ACCESS_DENIED;
6180 command = talloc_asprintf(ctx,
6181 "%s \"%s\" \"%s\"", cmd, portname, uri );
6182 if (!command) {
6183 return WERR_NOMEM;
6186 if ( token )
6187 is_print_op = user_has_privileges( token, &se_printop );
6189 DEBUG(10,("Running [%s]\n", command));
6191 /********* BEGIN SePrintOperatorPrivilege **********/
6193 if ( is_print_op )
6194 become_root();
6196 ret = smbrun(command, NULL);
6198 if ( is_print_op )
6199 unbecome_root();
6201 /********* END SePrintOperatorPrivilege **********/
6203 DEBUGADD(10,("returned [%d]\n", ret));
6205 TALLOC_FREE(command);
6207 if ( ret != 0 ) {
6208 return WERR_ACCESS_DENIED;
6211 return WERR_OK;
6214 /****************************************************************************
6215 ****************************************************************************/
6217 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6219 char *cmd = lp_addprinter_cmd();
6220 char **qlines;
6221 char *command = NULL;
6222 int numlines;
6223 int ret;
6224 int fd;
6225 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6226 bool is_print_op = False;
6227 char *remote_machine = talloc_strdup(ctx, "%m");
6229 if (!remote_machine) {
6230 return false;
6232 remote_machine = talloc_sub_basic(ctx,
6233 current_user_info.smb_name,
6234 current_user_info.domain,
6235 remote_machine);
6236 if (!remote_machine) {
6237 return false;
6240 command = talloc_asprintf(ctx,
6241 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6242 cmd, printer->info_2->printername, printer->info_2->sharename,
6243 printer->info_2->portname, printer->info_2->drivername,
6244 printer->info_2->location, printer->info_2->comment, remote_machine);
6245 if (!command) {
6246 return false;
6249 if ( token )
6250 is_print_op = user_has_privileges( token, &se_printop );
6252 DEBUG(10,("Running [%s]\n", command));
6254 /********* BEGIN SePrintOperatorPrivilege **********/
6256 if ( is_print_op )
6257 become_root();
6259 if ( (ret = smbrun(command, &fd)) == 0 ) {
6260 /* Tell everyone we updated smb.conf. */
6261 message_send_all(smbd_messaging_context(),
6262 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6265 if ( is_print_op )
6266 unbecome_root();
6268 /********* END SePrintOperatorPrivilege **********/
6270 DEBUGADD(10,("returned [%d]\n", ret));
6272 TALLOC_FREE(command);
6273 TALLOC_FREE(remote_machine);
6275 if ( ret != 0 ) {
6276 if (fd != -1)
6277 close(fd);
6278 return False;
6281 /* reload our services immediately */
6282 reload_services( False );
6284 numlines = 0;
6285 /* Get lines and convert them back to dos-codepage */
6286 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6287 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6288 close(fd);
6290 /* Set the portname to what the script says the portname should be. */
6291 /* but don't require anything to be return from the script exit a good error code */
6293 if (numlines) {
6294 /* Set the portname to what the script says the portname should be. */
6295 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6296 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6299 TALLOC_FREE(qlines);
6300 return True;
6304 /********************************************************************
6305 * Called by spoolss_api_setprinter
6306 * when updating a printer description.
6307 ********************************************************************/
6309 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6310 const SPOOL_PRINTER_INFO_LEVEL *info,
6311 DEVICEMODE *devmode)
6313 int snum;
6314 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6315 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6316 WERROR result;
6317 UNISTR2 buffer;
6318 fstring asc_buffer;
6320 DEBUG(8,("update_printer\n"));
6322 result = WERR_OK;
6324 if (!Printer) {
6325 result = WERR_BADFID;
6326 goto done;
6329 if (!get_printer_snum(p, handle, &snum, NULL)) {
6330 result = WERR_BADFID;
6331 goto done;
6334 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6335 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6336 result = WERR_BADFID;
6337 goto done;
6340 DEBUGADD(8,("Converting info_2 struct\n"));
6343 * convert_printer_info converts the incoming
6344 * info from the client and overwrites the info
6345 * just read from the tdb in the pointer 'printer'.
6348 if (!convert_printer_info(info, printer, level)) {
6349 result = WERR_NOMEM;
6350 goto done;
6353 if (devmode) {
6354 /* we have a valid devmode
6355 convert it and link it*/
6357 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6358 if (!convert_devicemode(printer->info_2->printername, devmode,
6359 &printer->info_2->devmode)) {
6360 result = WERR_NOMEM;
6361 goto done;
6365 /* Do sanity check on the requested changes for Samba */
6367 if (!check_printer_ok(printer->info_2, snum)) {
6368 result = WERR_INVALID_PARAM;
6369 goto done;
6372 /* FIXME!!! If the driver has changed we really should verify that
6373 it is installed before doing much else --jerry */
6375 /* Check calling user has permission to update printer description */
6377 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6378 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6379 result = WERR_ACCESS_DENIED;
6380 goto done;
6383 /* Call addprinter hook */
6384 /* Check changes to see if this is really needed */
6386 if ( *lp_addprinter_cmd()
6387 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6388 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6389 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6390 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6392 /* add_printer_hook() will call reload_services() */
6394 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6395 printer) ) {
6396 result = WERR_ACCESS_DENIED;
6397 goto done;
6402 * When a *new* driver is bound to a printer, the drivername is used to
6403 * lookup previously saved driver initialization info, which is then
6404 * bound to the printer, simulating what happens in the Windows arch.
6406 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6408 if (!set_driver_init(printer, 2))
6410 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6411 printer->info_2->drivername));
6414 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6415 printer->info_2->drivername));
6417 notify_printer_driver(snum, printer->info_2->drivername);
6421 * flag which changes actually occured. This is a small subset of
6422 * all the possible changes. We also have to update things in the
6423 * DsSpooler key.
6426 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6427 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6428 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6429 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6431 notify_printer_comment(snum, printer->info_2->comment);
6434 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6435 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6436 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6437 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6439 notify_printer_sharename(snum, printer->info_2->sharename);
6442 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6443 char *pname;
6445 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6446 pname++;
6447 else
6448 pname = printer->info_2->printername;
6451 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6452 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6453 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6455 notify_printer_printername( snum, pname );
6458 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6459 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6460 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6461 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6463 notify_printer_port(snum, printer->info_2->portname);
6466 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6467 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6468 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6469 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6471 notify_printer_location(snum, printer->info_2->location);
6474 /* here we need to update some more DsSpooler keys */
6475 /* uNCName, serverName, shortServerName */
6477 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6478 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6479 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6480 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6481 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6483 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6484 global_myname(), printer->info_2->sharename );
6485 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6486 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6487 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6489 /* Update printer info */
6490 result = mod_a_printer(printer, 2);
6492 done:
6493 free_a_printer(&printer, 2);
6494 free_a_printer(&old_printer, 2);
6497 return result;
6500 /****************************************************************************
6501 ****************************************************************************/
6502 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6503 const SPOOL_PRINTER_INFO_LEVEL *info)
6505 #ifdef HAVE_ADS
6506 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6507 int snum;
6508 Printer_entry *Printer;
6510 if ( lp_security() != SEC_ADS ) {
6511 return WERR_UNKNOWN_LEVEL;
6514 Printer = find_printer_index_by_hnd(p, handle);
6516 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6518 if (!Printer)
6519 return WERR_BADFID;
6521 if (!get_printer_snum(p, handle, &snum, NULL))
6522 return WERR_BADFID;
6524 nt_printer_publish(Printer, snum, info7->action);
6526 return WERR_OK;
6527 #else
6528 return WERR_UNKNOWN_LEVEL;
6529 #endif
6531 /****************************************************************************
6532 ****************************************************************************/
6534 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6536 POLICY_HND *handle = &q_u->handle;
6537 uint32 level = q_u->level;
6538 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6539 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6540 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6541 uint32 command = q_u->command;
6542 WERROR result;
6544 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6546 if (!Printer) {
6547 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6548 return WERR_BADFID;
6551 /* check the level */
6552 switch (level) {
6553 case 0:
6554 return control_printer(handle, command, p);
6555 case 2:
6556 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6557 if (!W_ERROR_IS_OK(result))
6558 return result;
6559 if (secdesc_ctr)
6560 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6561 return result;
6562 case 3:
6563 return update_printer_sec(handle, level, info, p,
6564 secdesc_ctr);
6565 case 7:
6566 return publish_or_unpublish_printer(p, handle, info);
6567 default:
6568 return WERR_UNKNOWN_LEVEL;
6572 /****************************************************************************
6573 ****************************************************************************/
6575 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6577 POLICY_HND *handle = &q_u->handle;
6578 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6580 if (!Printer) {
6581 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6582 return WERR_BADFID;
6585 if (Printer->notify.client_connected==True) {
6586 int snum = -1;
6588 if ( Printer->printer_type == SPLHND_SERVER)
6589 snum = -1;
6590 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6591 !get_printer_snum(p, handle, &snum, NULL) )
6592 return WERR_BADFID;
6594 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6597 Printer->notify.flags=0;
6598 Printer->notify.options=0;
6599 Printer->notify.localmachine[0]='\0';
6600 Printer->notify.printerlocal=0;
6601 if (Printer->notify.option)
6602 free_spool_notify_option(&Printer->notify.option);
6603 Printer->notify.client_connected=False;
6605 return WERR_OK;
6608 /****************************************************************************
6609 ****************************************************************************/
6611 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6613 /* that's an [in out] buffer */
6615 if (!q_u->buffer && (q_u->offered!=0)) {
6616 return WERR_INVALID_PARAM;
6619 rpcbuf_move(q_u->buffer, &r_u->buffer);
6621 r_u->needed = 0;
6622 return WERR_INVALID_PARAM; /* this is what a NT server
6623 returns for AddJob. AddJob
6624 must fail on non-local
6625 printers */
6628 /****************************************************************************
6629 ****************************************************************************/
6631 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6632 int position, int snum,
6633 const NT_PRINTER_INFO_LEVEL *ntprinter)
6635 struct tm *t;
6637 t=gmtime(&queue->time);
6639 job_info->jobid=queue->job;
6640 init_unistr(&job_info->printername, lp_servicename(snum));
6641 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6642 init_unistr(&job_info->username, queue->fs_user);
6643 init_unistr(&job_info->document, queue->fs_file);
6644 init_unistr(&job_info->datatype, "RAW");
6645 init_unistr(&job_info->text_status, "");
6646 job_info->status=nt_printj_status(queue->status);
6647 job_info->priority=queue->priority;
6648 job_info->position=position;
6649 job_info->totalpages=queue->page_count;
6650 job_info->pagesprinted=0;
6652 make_systemtime(&job_info->submitted, t);
6655 /****************************************************************************
6656 ****************************************************************************/
6658 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6659 int position, int snum,
6660 const NT_PRINTER_INFO_LEVEL *ntprinter,
6661 DEVICEMODE *devmode)
6663 struct tm *t;
6665 t=gmtime(&queue->time);
6667 job_info->jobid=queue->job;
6669 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6671 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6672 init_unistr(&job_info->username, queue->fs_user);
6673 init_unistr(&job_info->document, queue->fs_file);
6674 init_unistr(&job_info->notifyname, queue->fs_user);
6675 init_unistr(&job_info->datatype, "RAW");
6676 init_unistr(&job_info->printprocessor, "winprint");
6677 init_unistr(&job_info->parameters, "");
6678 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6679 init_unistr(&job_info->text_status, "");
6681 /* and here the security descriptor */
6683 job_info->status=nt_printj_status(queue->status);
6684 job_info->priority=queue->priority;
6685 job_info->position=position;
6686 job_info->starttime=0;
6687 job_info->untiltime=0;
6688 job_info->totalpages=queue->page_count;
6689 job_info->size=queue->size;
6690 make_systemtime(&(job_info->submitted), t);
6691 job_info->timeelapsed=0;
6692 job_info->pagesprinted=0;
6694 job_info->devmode = devmode;
6696 return (True);
6699 /****************************************************************************
6700 Enumjobs at level 1.
6701 ****************************************************************************/
6703 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6704 const NT_PRINTER_INFO_LEVEL *ntprinter,
6705 RPC_BUFFER *buffer, uint32 offered,
6706 uint32 *needed, uint32 *returned)
6708 JOB_INFO_1 *info;
6709 int i;
6710 WERROR result = WERR_OK;
6712 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6713 if (info==NULL) {
6714 *returned=0;
6715 return WERR_NOMEM;
6718 for (i=0; i<*returned; i++)
6719 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6721 /* check the required size. */
6722 for (i=0; i<*returned; i++)
6723 (*needed) += spoolss_size_job_info_1(&info[i]);
6725 if (*needed > offered) {
6726 result = WERR_INSUFFICIENT_BUFFER;
6727 goto out;
6730 if (!rpcbuf_alloc_size(buffer, *needed)) {
6731 result = WERR_NOMEM;
6732 goto out;
6735 /* fill the buffer with the structures */
6736 for (i=0; i<*returned; i++)
6737 smb_io_job_info_1("", buffer, &info[i], 0);
6739 out:
6740 /* clear memory */
6741 SAFE_FREE(info);
6743 if ( !W_ERROR_IS_OK(result) )
6744 *returned = 0;
6746 return result;
6749 /****************************************************************************
6750 Enumjobs at level 2.
6751 ****************************************************************************/
6753 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6754 const NT_PRINTER_INFO_LEVEL *ntprinter,
6755 RPC_BUFFER *buffer, uint32 offered,
6756 uint32 *needed, uint32 *returned)
6758 JOB_INFO_2 *info = NULL;
6759 int i;
6760 WERROR result = WERR_OK;
6761 DEVICEMODE *devmode = NULL;
6763 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6764 *returned=0;
6765 return WERR_NOMEM;
6768 /* this should not be a failure condition if the devmode is NULL */
6770 devmode = construct_dev_mode(lp_const_servicename(snum));
6772 for (i=0; i<*returned; i++)
6773 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6775 /* check the required size. */
6776 for (i=0; i<*returned; i++)
6777 (*needed) += spoolss_size_job_info_2(&info[i]);
6779 if (*needed > offered) {
6780 result = WERR_INSUFFICIENT_BUFFER;
6781 goto out;
6784 if (!rpcbuf_alloc_size(buffer, *needed)) {
6785 result = WERR_NOMEM;
6786 goto out;
6789 /* fill the buffer with the structures */
6790 for (i=0; i<*returned; i++)
6791 smb_io_job_info_2("", buffer, &info[i], 0);
6793 out:
6794 free_devmode(devmode);
6795 SAFE_FREE(info);
6797 if ( !W_ERROR_IS_OK(result) )
6798 *returned = 0;
6800 return result;
6804 /****************************************************************************
6805 Enumjobs.
6806 ****************************************************************************/
6808 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6810 POLICY_HND *handle = &q_u->handle;
6811 uint32 level = q_u->level;
6812 RPC_BUFFER *buffer = NULL;
6813 uint32 offered = q_u->offered;
6814 uint32 *needed = &r_u->needed;
6815 uint32 *returned = &r_u->returned;
6816 WERROR wret;
6817 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6818 int snum;
6819 print_status_struct prt_status;
6820 print_queue_struct *queue=NULL;
6822 /* that's an [in out] buffer */
6824 if (!q_u->buffer && (offered!=0)) {
6825 return WERR_INVALID_PARAM;
6828 rpcbuf_move(q_u->buffer, &r_u->buffer);
6829 buffer = r_u->buffer;
6831 DEBUG(4,("_spoolss_enumjobs\n"));
6833 *needed=0;
6834 *returned=0;
6836 /* lookup the printer snum and tdb entry */
6838 if (!get_printer_snum(p, handle, &snum, NULL))
6839 return WERR_BADFID;
6841 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6842 if ( !W_ERROR_IS_OK(wret) )
6843 return wret;
6845 *returned = print_queue_status(snum, &queue, &prt_status);
6846 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6848 if (*returned == 0) {
6849 SAFE_FREE(queue);
6850 free_a_printer(&ntprinter, 2);
6851 return WERR_OK;
6854 switch (level) {
6855 case 1:
6856 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6857 break;
6858 case 2:
6859 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6860 break;
6861 default:
6862 *returned=0;
6863 wret = WERR_UNKNOWN_LEVEL;
6864 break;
6867 SAFE_FREE(queue);
6868 free_a_printer( &ntprinter, 2 );
6869 return wret;
6872 /****************************************************************************
6873 ****************************************************************************/
6875 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6877 return WERR_OK;
6880 /****************************************************************************
6881 ****************************************************************************/
6883 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6885 POLICY_HND *handle = &q_u->handle;
6886 uint32 jobid = q_u->jobid;
6887 uint32 command = q_u->command;
6889 int snum;
6890 WERROR errcode = WERR_BADFUNC;
6892 if (!get_printer_snum(p, handle, &snum, NULL)) {
6893 return WERR_BADFID;
6896 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6897 return WERR_INVALID_PRINTER_NAME;
6900 switch (command) {
6901 case JOB_CONTROL_CANCEL:
6902 case JOB_CONTROL_DELETE:
6903 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6904 errcode = WERR_OK;
6906 break;
6907 case JOB_CONTROL_PAUSE:
6908 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6909 errcode = WERR_OK;
6911 break;
6912 case JOB_CONTROL_RESTART:
6913 case JOB_CONTROL_RESUME:
6914 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6915 errcode = WERR_OK;
6917 break;
6918 default:
6919 return WERR_UNKNOWN_LEVEL;
6922 return errcode;
6925 /****************************************************************************
6926 Enumerates all printer drivers at level 1.
6927 ****************************************************************************/
6929 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6931 int i;
6932 int ndrivers;
6933 uint32 version;
6934 fstring *list = NULL;
6935 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6936 DRIVER_INFO_1 *driver_info_1=NULL;
6937 WERROR result = WERR_OK;
6939 *returned=0;
6941 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6942 list=NULL;
6943 ndrivers=get_ntdrivers(&list, architecture, version);
6944 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6946 if(ndrivers == -1) {
6947 SAFE_FREE(driver_info_1);
6948 return WERR_NOMEM;
6951 if(ndrivers != 0) {
6952 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6953 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6954 SAFE_FREE(list);
6955 return WERR_NOMEM;
6959 for (i=0; i<ndrivers; i++) {
6960 WERROR status;
6961 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6962 ZERO_STRUCT(driver);
6963 status = get_a_printer_driver(&driver, 3, list[i],
6964 architecture, version);
6965 if (!W_ERROR_IS_OK(status)) {
6966 SAFE_FREE(list);
6967 SAFE_FREE(driver_info_1);
6968 return status;
6970 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6971 free_a_printer_driver(driver, 3);
6974 *returned+=ndrivers;
6975 SAFE_FREE(list);
6978 /* check the required size. */
6979 for (i=0; i<*returned; i++) {
6980 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6981 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6984 if (*needed > offered) {
6985 result = WERR_INSUFFICIENT_BUFFER;
6986 goto out;
6989 if (!rpcbuf_alloc_size(buffer, *needed)) {
6990 result = WERR_NOMEM;
6991 goto out;
6994 /* fill the buffer with the driver structures */
6995 for (i=0; i<*returned; i++) {
6996 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6997 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7000 out:
7001 SAFE_FREE(driver_info_1);
7003 if ( !W_ERROR_IS_OK(result) )
7004 *returned = 0;
7006 return result;
7009 /****************************************************************************
7010 Enumerates all printer drivers at level 2.
7011 ****************************************************************************/
7013 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7015 int i;
7016 int ndrivers;
7017 uint32 version;
7018 fstring *list = NULL;
7019 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7020 DRIVER_INFO_2 *driver_info_2=NULL;
7021 WERROR result = WERR_OK;
7023 *returned=0;
7025 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7026 list=NULL;
7027 ndrivers=get_ntdrivers(&list, architecture, version);
7028 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7030 if(ndrivers == -1) {
7031 SAFE_FREE(driver_info_2);
7032 return WERR_NOMEM;
7035 if(ndrivers != 0) {
7036 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7037 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7038 SAFE_FREE(list);
7039 return WERR_NOMEM;
7043 for (i=0; i<ndrivers; i++) {
7044 WERROR status;
7046 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7047 ZERO_STRUCT(driver);
7048 status = get_a_printer_driver(&driver, 3, list[i],
7049 architecture, version);
7050 if (!W_ERROR_IS_OK(status)) {
7051 SAFE_FREE(list);
7052 SAFE_FREE(driver_info_2);
7053 return status;
7055 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7056 free_a_printer_driver(driver, 3);
7059 *returned+=ndrivers;
7060 SAFE_FREE(list);
7063 /* check the required size. */
7064 for (i=0; i<*returned; i++) {
7065 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7066 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7069 if (*needed > offered) {
7070 result = WERR_INSUFFICIENT_BUFFER;
7071 goto out;
7074 if (!rpcbuf_alloc_size(buffer, *needed)) {
7075 result = WERR_NOMEM;
7076 goto out;
7079 /* fill the buffer with the form structures */
7080 for (i=0; i<*returned; i++) {
7081 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7082 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7085 out:
7086 SAFE_FREE(driver_info_2);
7088 if ( !W_ERROR_IS_OK(result) )
7089 *returned = 0;
7091 return result;
7094 /****************************************************************************
7095 Enumerates all printer drivers at level 3.
7096 ****************************************************************************/
7098 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7100 int i;
7101 int ndrivers;
7102 uint32 version;
7103 fstring *list = NULL;
7104 DRIVER_INFO_3 *driver_info_3=NULL;
7105 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7106 WERROR result = WERR_OK;
7108 *returned=0;
7110 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7111 list=NULL;
7112 ndrivers=get_ntdrivers(&list, architecture, version);
7113 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7115 if(ndrivers == -1) {
7116 SAFE_FREE(driver_info_3);
7117 return WERR_NOMEM;
7120 if(ndrivers != 0) {
7121 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7122 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7123 SAFE_FREE(list);
7124 return WERR_NOMEM;
7128 for (i=0; i<ndrivers; i++) {
7129 WERROR status;
7131 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7132 ZERO_STRUCT(driver);
7133 status = get_a_printer_driver(&driver, 3, list[i],
7134 architecture, version);
7135 if (!W_ERROR_IS_OK(status)) {
7136 SAFE_FREE(list);
7137 SAFE_FREE(driver_info_3);
7138 return status;
7140 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7141 free_a_printer_driver(driver, 3);
7144 *returned+=ndrivers;
7145 SAFE_FREE(list);
7148 /* check the required size. */
7149 for (i=0; i<*returned; i++) {
7150 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7151 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7154 if (*needed > offered) {
7155 result = WERR_INSUFFICIENT_BUFFER;
7156 goto out;
7159 if (!rpcbuf_alloc_size(buffer, *needed)) {
7160 result = WERR_NOMEM;
7161 goto out;
7164 /* fill the buffer with the driver structures */
7165 for (i=0; i<*returned; i++) {
7166 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7167 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7170 out:
7171 for (i=0; i<*returned; i++) {
7172 SAFE_FREE(driver_info_3[i].dependentfiles);
7175 SAFE_FREE(driver_info_3);
7177 if ( !W_ERROR_IS_OK(result) )
7178 *returned = 0;
7180 return result;
7183 /****************************************************************************
7184 Enumerates all printer drivers.
7185 ****************************************************************************/
7187 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7189 uint32 level = q_u->level;
7190 RPC_BUFFER *buffer = NULL;
7191 uint32 offered = q_u->offered;
7192 uint32 *needed = &r_u->needed;
7193 uint32 *returned = &r_u->returned;
7194 const char *cservername;
7195 fstring servername;
7196 fstring architecture;
7198 /* that's an [in out] buffer */
7200 if (!q_u->buffer && (offered!=0)) {
7201 return WERR_INVALID_PARAM;
7204 rpcbuf_move(q_u->buffer, &r_u->buffer);
7205 buffer = r_u->buffer;
7207 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7209 *needed = 0;
7210 *returned = 0;
7212 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7213 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7215 cservername = canon_servername(servername);
7217 if (!is_myname_or_ipaddr(cservername))
7218 return WERR_UNKNOWN_PRINTER_DRIVER;
7220 switch (level) {
7221 case 1:
7222 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7223 case 2:
7224 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7225 case 3:
7226 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7227 default:
7228 return WERR_UNKNOWN_LEVEL;
7232 /****************************************************************************
7233 ****************************************************************************/
7235 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7237 form->flag=list->flag;
7238 init_unistr(&form->name, list->name);
7239 form->width=list->width;
7240 form->length=list->length;
7241 form->left=list->left;
7242 form->top=list->top;
7243 form->right=list->right;
7244 form->bottom=list->bottom;
7247 /****************************************************************************
7248 ****************************************************************************/
7250 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7252 uint32 level = q_u->level;
7253 RPC_BUFFER *buffer = NULL;
7254 uint32 offered = q_u->offered;
7255 uint32 *needed = &r_u->needed;
7256 uint32 *numofforms = &r_u->numofforms;
7257 uint32 numbuiltinforms;
7259 nt_forms_struct *list=NULL;
7260 nt_forms_struct *builtinlist=NULL;
7261 FORM_1 *forms_1;
7262 int buffer_size=0;
7263 int i;
7265 /* that's an [in out] buffer */
7267 if (!q_u->buffer && (offered!=0) ) {
7268 return WERR_INVALID_PARAM;
7271 rpcbuf_move(q_u->buffer, &r_u->buffer);
7272 buffer = r_u->buffer;
7274 DEBUG(4,("_spoolss_enumforms\n"));
7275 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7276 DEBUGADD(5,("Info level [%d]\n", level));
7278 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7279 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7280 *numofforms = get_ntforms(&list);
7281 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7282 *numofforms += numbuiltinforms;
7284 if (*numofforms == 0) {
7285 SAFE_FREE(builtinlist);
7286 SAFE_FREE(list);
7287 return WERR_NO_MORE_ITEMS;
7290 switch (level) {
7291 case 1:
7292 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7293 SAFE_FREE(builtinlist);
7294 SAFE_FREE(list);
7295 *numofforms=0;
7296 return WERR_NOMEM;
7299 /* construct the list of form structures */
7300 for (i=0; i<numbuiltinforms; i++) {
7301 DEBUGADD(6,("Filling form number [%d]\n",i));
7302 fill_form_1(&forms_1[i], &builtinlist[i]);
7305 SAFE_FREE(builtinlist);
7307 for (; i<*numofforms; i++) {
7308 DEBUGADD(6,("Filling form number [%d]\n",i));
7309 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7312 SAFE_FREE(list);
7314 /* check the required size. */
7315 for (i=0; i<numbuiltinforms; i++) {
7316 DEBUGADD(6,("adding form [%d]'s size\n",i));
7317 buffer_size += spoolss_size_form_1(&forms_1[i]);
7319 for (; i<*numofforms; i++) {
7320 DEBUGADD(6,("adding form [%d]'s size\n",i));
7321 buffer_size += spoolss_size_form_1(&forms_1[i]);
7324 *needed=buffer_size;
7326 if (*needed > offered) {
7327 SAFE_FREE(forms_1);
7328 *numofforms=0;
7329 return WERR_INSUFFICIENT_BUFFER;
7332 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7333 SAFE_FREE(forms_1);
7334 *numofforms=0;
7335 return WERR_NOMEM;
7338 /* fill the buffer with the form structures */
7339 for (i=0; i<numbuiltinforms; i++) {
7340 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7341 smb_io_form_1("", buffer, &forms_1[i], 0);
7343 for (; i<*numofforms; i++) {
7344 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7345 smb_io_form_1("", buffer, &forms_1[i], 0);
7348 SAFE_FREE(forms_1);
7350 return WERR_OK;
7352 default:
7353 SAFE_FREE(list);
7354 SAFE_FREE(builtinlist);
7355 return WERR_UNKNOWN_LEVEL;
7359 /****************************************************************************
7360 ****************************************************************************/
7362 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7364 uint32 level = q_u->level;
7365 UNISTR2 *uni_formname = &q_u->formname;
7366 RPC_BUFFER *buffer = NULL;
7367 uint32 offered = q_u->offered;
7368 uint32 *needed = &r_u->needed;
7370 nt_forms_struct *list=NULL;
7371 nt_forms_struct builtin_form;
7372 bool foundBuiltin;
7373 FORM_1 form_1;
7374 fstring form_name;
7375 int buffer_size=0;
7376 int numofforms=0, i=0;
7378 /* that's an [in out] buffer */
7380 if (!q_u->buffer && (offered!=0)) {
7381 return WERR_INVALID_PARAM;
7384 rpcbuf_move(q_u->buffer, &r_u->buffer);
7385 buffer = r_u->buffer;
7387 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7389 DEBUG(4,("_spoolss_getform\n"));
7390 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7391 DEBUGADD(5,("Info level [%d]\n", level));
7393 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7394 if (!foundBuiltin) {
7395 numofforms = get_ntforms(&list);
7396 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7398 if (numofforms == 0)
7399 return WERR_BADFID;
7402 switch (level) {
7403 case 1:
7404 if (foundBuiltin) {
7405 fill_form_1(&form_1, &builtin_form);
7406 } else {
7408 /* Check if the requested name is in the list of form structures */
7409 for (i=0; i<numofforms; i++) {
7411 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7413 if (strequal(form_name, list[i].name)) {
7414 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7415 fill_form_1(&form_1, &list[i]);
7416 break;
7420 SAFE_FREE(list);
7421 if (i == numofforms) {
7422 return WERR_BADFID;
7425 /* check the required size. */
7427 *needed=spoolss_size_form_1(&form_1);
7429 if (*needed > offered)
7430 return WERR_INSUFFICIENT_BUFFER;
7432 if (!rpcbuf_alloc_size(buffer, buffer_size))
7433 return WERR_NOMEM;
7435 /* fill the buffer with the form structures */
7436 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7437 smb_io_form_1("", buffer, &form_1, 0);
7439 return WERR_OK;
7441 default:
7442 SAFE_FREE(list);
7443 return WERR_UNKNOWN_LEVEL;
7447 /****************************************************************************
7448 ****************************************************************************/
7450 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7452 init_unistr(&port->port_name, name);
7455 /****************************************************************************
7456 TODO: This probably needs distinguish between TCP/IP and Local ports
7457 somehow.
7458 ****************************************************************************/
7460 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7462 init_unistr(&port->port_name, name);
7463 init_unistr(&port->monitor_name, "Local Monitor");
7464 init_unistr(&port->description, SPL_LOCAL_PORT );
7465 port->port_type=PORT_TYPE_WRITE;
7466 port->reserved=0x0;
7470 /****************************************************************************
7471 wrapper around the enumer ports command
7472 ****************************************************************************/
7474 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7476 char *cmd = lp_enumports_cmd();
7477 char **qlines = NULL;
7478 char *command = NULL;
7479 int numlines;
7480 int ret;
7481 int fd;
7483 *count = 0;
7484 *lines = NULL;
7486 /* if no hook then just fill in the default port */
7488 if ( !*cmd ) {
7489 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7490 return WERR_NOMEM;
7492 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7493 TALLOC_FREE(qlines);
7494 return WERR_NOMEM;
7496 qlines[1] = NULL;
7497 numlines = 1;
7499 else {
7500 /* we have a valid enumport command */
7502 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7503 if (!command) {
7504 return WERR_NOMEM;
7507 DEBUG(10,("Running [%s]\n", command));
7508 ret = smbrun(command, &fd);
7509 DEBUG(10,("Returned [%d]\n", ret));
7510 TALLOC_FREE(command);
7511 if (ret != 0) {
7512 if (fd != -1) {
7513 close(fd);
7515 return WERR_ACCESS_DENIED;
7518 numlines = 0;
7519 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7520 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7521 close(fd);
7524 *count = numlines;
7525 *lines = qlines;
7527 return WERR_OK;
7530 /****************************************************************************
7531 enumports level 1.
7532 ****************************************************************************/
7534 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7536 PORT_INFO_1 *ports=NULL;
7537 int i=0;
7538 WERROR result = WERR_OK;
7539 char **qlines = NULL;
7540 int numlines = 0;
7542 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7543 if (!W_ERROR_IS_OK(result)) {
7544 TALLOC_FREE(qlines);
7545 return result;
7548 if(numlines) {
7549 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7550 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7551 win_errstr(WERR_NOMEM)));
7552 TALLOC_FREE(qlines);
7553 return WERR_NOMEM;
7556 for (i=0; i<numlines; i++) {
7557 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7558 fill_port_1(&ports[i], qlines[i]);
7561 TALLOC_FREE(qlines);
7563 *returned = numlines;
7565 /* check the required size. */
7566 for (i=0; i<*returned; i++) {
7567 DEBUGADD(6,("adding port [%d]'s size\n", i));
7568 *needed += spoolss_size_port_info_1(&ports[i]);
7571 if (*needed > offered) {
7572 result = WERR_INSUFFICIENT_BUFFER;
7573 goto out;
7576 if (!rpcbuf_alloc_size(buffer, *needed)) {
7577 result = WERR_NOMEM;
7578 goto out;
7581 /* fill the buffer with the ports structures */
7582 for (i=0; i<*returned; i++) {
7583 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7584 smb_io_port_1("", buffer, &ports[i], 0);
7587 out:
7588 SAFE_FREE(ports);
7590 if ( !W_ERROR_IS_OK(result) )
7591 *returned = 0;
7593 return result;
7596 /****************************************************************************
7597 enumports level 2.
7598 ****************************************************************************/
7600 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7602 PORT_INFO_2 *ports=NULL;
7603 int i=0;
7604 WERROR result = WERR_OK;
7605 char **qlines = NULL;
7606 int numlines = 0;
7608 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7609 if ( !W_ERROR_IS_OK(result)) {
7610 TALLOC_FREE(qlines);
7611 return result;
7614 if(numlines) {
7615 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7616 TALLOC_FREE(qlines);
7617 return WERR_NOMEM;
7620 for (i=0; i<numlines; i++) {
7621 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7622 fill_port_2(&(ports[i]), qlines[i]);
7626 TALLOC_FREE(qlines);
7628 *returned = numlines;
7630 /* check the required size. */
7631 for (i=0; i<*returned; i++) {
7632 DEBUGADD(6,("adding port [%d]'s size\n", i));
7633 *needed += spoolss_size_port_info_2(&ports[i]);
7636 if (*needed > offered) {
7637 result = WERR_INSUFFICIENT_BUFFER;
7638 goto out;
7641 if (!rpcbuf_alloc_size(buffer, *needed)) {
7642 result = WERR_NOMEM;
7643 goto out;
7646 /* fill the buffer with the ports structures */
7647 for (i=0; i<*returned; i++) {
7648 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7649 smb_io_port_2("", buffer, &ports[i], 0);
7652 out:
7653 SAFE_FREE(ports);
7655 if ( !W_ERROR_IS_OK(result) )
7656 *returned = 0;
7658 return result;
7661 /****************************************************************************
7662 enumports.
7663 ****************************************************************************/
7665 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7667 uint32 level = q_u->level;
7668 RPC_BUFFER *buffer = NULL;
7669 uint32 offered = q_u->offered;
7670 uint32 *needed = &r_u->needed;
7671 uint32 *returned = &r_u->returned;
7673 /* that's an [in out] buffer */
7675 if (!q_u->buffer && (offered!=0)) {
7676 return WERR_INVALID_PARAM;
7679 rpcbuf_move(q_u->buffer, &r_u->buffer);
7680 buffer = r_u->buffer;
7682 DEBUG(4,("_spoolss_enumports\n"));
7684 *returned=0;
7685 *needed=0;
7687 switch (level) {
7688 case 1:
7689 return enumports_level_1(buffer, offered, needed, returned);
7690 case 2:
7691 return enumports_level_2(buffer, offered, needed, returned);
7692 default:
7693 return WERR_UNKNOWN_LEVEL;
7697 /****************************************************************************
7698 ****************************************************************************/
7700 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7701 const SPOOL_PRINTER_INFO_LEVEL *info,
7702 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7703 uint32 user_switch, const SPOOL_USER_CTR *user,
7704 POLICY_HND *handle)
7706 NT_PRINTER_INFO_LEVEL *printer = NULL;
7707 fstring name;
7708 int snum;
7709 WERROR err = WERR_OK;
7711 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7712 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7713 return WERR_NOMEM;
7716 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7717 if (!convert_printer_info(info, printer, 2)) {
7718 free_a_printer(&printer, 2);
7719 return WERR_NOMEM;
7722 /* check to see if the printer already exists */
7724 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7725 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7726 printer->info_2->sharename));
7727 free_a_printer(&printer, 2);
7728 return WERR_PRINTER_ALREADY_EXISTS;
7731 /* FIXME!!! smbd should check to see if the driver is installed before
7732 trying to add a printer like this --jerry */
7734 if (*lp_addprinter_cmd() ) {
7735 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7736 printer) ) {
7737 free_a_printer(&printer,2);
7738 return WERR_ACCESS_DENIED;
7740 } else {
7741 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7742 "smb.conf parameter \"addprinter command\" is defined. This"
7743 "parameter must exist for this call to succeed\n",
7744 printer->info_2->sharename ));
7747 /* use our primary netbios name since get_a_printer() will convert
7748 it to what the client expects on a case by case basis */
7750 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7751 printer->info_2->sharename);
7754 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7755 free_a_printer(&printer,2);
7756 return WERR_ACCESS_DENIED;
7759 /* you must be a printer admin to add a new printer */
7760 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7761 free_a_printer(&printer,2);
7762 return WERR_ACCESS_DENIED;
7766 * Do sanity check on the requested changes for Samba.
7769 if (!check_printer_ok(printer->info_2, snum)) {
7770 free_a_printer(&printer,2);
7771 return WERR_INVALID_PARAM;
7775 * When a printer is created, the drivername bound to the printer is used
7776 * to lookup previously saved driver initialization info, which is then
7777 * bound to the new printer, simulating what happens in the Windows arch.
7780 if (!devmode)
7782 set_driver_init(printer, 2);
7784 else
7786 /* A valid devmode was included, convert and link it
7788 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7790 if (!convert_devicemode(printer->info_2->printername, devmode,
7791 &printer->info_2->devmode))
7792 return WERR_NOMEM;
7795 /* write the ASCII on disk */
7796 err = mod_a_printer(printer, 2);
7797 if (!W_ERROR_IS_OK(err)) {
7798 free_a_printer(&printer,2);
7799 return err;
7802 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7803 /* Handle open failed - remove addition. */
7804 del_a_printer(printer->info_2->sharename);
7805 free_a_printer(&printer,2);
7806 return WERR_ACCESS_DENIED;
7809 update_c_setprinter(False);
7810 free_a_printer(&printer,2);
7812 return WERR_OK;
7815 /****************************************************************************
7816 ****************************************************************************/
7818 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7820 UNISTR2 *uni_srv_name = q_u->server_name;
7821 uint32 level = q_u->level;
7822 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7823 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7824 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7825 uint32 user_switch = q_u->user_switch;
7826 SPOOL_USER_CTR *user = &q_u->user_ctr;
7827 POLICY_HND *handle = &r_u->handle;
7829 switch (level) {
7830 case 1:
7831 /* we don't handle yet */
7832 /* but I know what to do ... */
7833 return WERR_UNKNOWN_LEVEL;
7834 case 2:
7835 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7836 devmode, sdb,
7837 user_switch, user, handle);
7838 default:
7839 return WERR_UNKNOWN_LEVEL;
7843 /****************************************************************************
7844 ****************************************************************************/
7846 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7848 uint32 level = q_u->level;
7849 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7850 WERROR err = WERR_OK;
7851 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7852 fstring driver_name;
7853 uint32 version;
7855 ZERO_STRUCT(driver);
7857 if (!convert_printer_driver_info(info, &driver, level)) {
7858 err = WERR_NOMEM;
7859 goto done;
7862 DEBUG(5,("Cleaning driver's information\n"));
7863 err = clean_up_driver_struct(p, driver, level);
7864 if (!W_ERROR_IS_OK(err))
7865 goto done;
7867 DEBUG(5,("Moving driver to final destination\n"));
7868 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7869 &err)) ) {
7870 goto done;
7873 if (add_a_printer_driver(driver, level)!=0) {
7874 err = WERR_ACCESS_DENIED;
7875 goto done;
7878 switch(level) {
7879 case 3:
7880 fstrcpy(driver_name,
7881 driver.info_3->name ? driver.info_3->name : "");
7882 break;
7883 case 6:
7884 fstrcpy(driver_name,
7885 driver.info_6->name ? driver.info_6->name : "");
7886 break;
7890 * I think this is where he DrvUpgradePrinter() hook would be
7891 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7892 * server. Right now, we just need to send ourselves a message
7893 * to update each printer bound to this driver. --jerry
7896 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7897 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7898 driver_name));
7902 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7903 * decide if the driver init data should be deleted. The rules are:
7904 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7905 * 2) delete init data only if there is no 2k/Xp driver
7906 * 3) always delete init data
7907 * The generalized rule is always use init data from the highest order driver.
7908 * It is necessary to follow the driver install by an initialization step to
7909 * finish off this process.
7911 if (level == 3)
7912 version = driver.info_3->cversion;
7913 else if (level == 6)
7914 version = driver.info_6->version;
7915 else
7916 version = -1;
7917 switch (version) {
7919 * 9x printer driver - never delete init data
7921 case 0:
7922 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7923 driver_name));
7924 break;
7927 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7928 * there is no 2k/Xp driver init data for this driver name.
7930 case 2:
7932 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7934 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7936 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7938 if (!del_driver_init(driver_name))
7939 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7940 } else {
7942 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7944 free_a_printer_driver(driver1,3);
7945 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7946 driver_name));
7949 break;
7952 * 2k or Xp printer driver - always delete init data
7954 case 3:
7955 if (!del_driver_init(driver_name))
7956 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7957 break;
7959 default:
7960 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7961 break;
7965 done:
7966 free_a_printer_driver(driver, level);
7967 return err;
7970 /********************************************************************
7971 * spoolss_addprinterdriverex
7972 ********************************************************************/
7974 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7976 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7977 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7980 * we only support the semantics of AddPrinterDriver()
7981 * i.e. only copy files that are newer than existing ones
7984 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7985 return WERR_ACCESS_DENIED;
7987 ZERO_STRUCT(q_u_local);
7988 ZERO_STRUCT(r_u_local);
7990 /* just pass the information off to _spoolss_addprinterdriver() */
7991 q_u_local.server_name_ptr = q_u->server_name_ptr;
7992 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7993 q_u_local.level = q_u->level;
7994 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7996 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7999 /****************************************************************************
8000 ****************************************************************************/
8002 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
8004 init_unistr(&info->name, name);
8007 /****************************************************************************
8008 ****************************************************************************/
8010 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
8012 char *path = NULL;
8013 char *long_archi = NULL;
8014 char *servername = NULL;
8015 const char *pservername = NULL;
8016 const char *short_archi;
8017 DRIVER_DIRECTORY_1 *info=NULL;
8018 WERROR result = WERR_OK;
8019 TALLOC_CTX *ctx = talloc_tos();
8021 servername = unistr2_to_ascii_talloc(ctx, name);
8022 if (!servername) {
8023 return WERR_NOMEM;
8025 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
8026 if (!long_archi) {
8027 return WERR_NOMEM;
8030 pservername = canon_servername(servername);
8032 if ( !is_myname_or_ipaddr(pservername))
8033 return WERR_INVALID_PARAM;
8035 if (!(short_archi = get_short_archi(long_archi)))
8036 return WERR_INVALID_ENVIRONMENT;
8038 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8039 return WERR_NOMEM;
8041 path = talloc_asprintf(ctx,
8042 "\\\\%s\\print$\\%s", pservername, short_archi);
8043 if (!path) {
8044 result = WERR_NOMEM;
8045 goto out;
8048 DEBUG(4,("printer driver directory: [%s]\n", path));
8050 fill_driverdir_1(info, path);
8052 *needed += spoolss_size_driverdir_info_1(info);
8054 if (*needed > offered) {
8055 result = WERR_INSUFFICIENT_BUFFER;
8056 goto out;
8059 if (!rpcbuf_alloc_size(buffer, *needed)) {
8060 result = WERR_NOMEM;
8061 goto out;
8064 smb_io_driverdir_1("", buffer, info, 0);
8066 out:
8067 SAFE_FREE(info);
8069 return result;
8072 /****************************************************************************
8073 ****************************************************************************/
8075 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8077 UNISTR2 *name = &q_u->name;
8078 UNISTR2 *uni_environment = &q_u->environment;
8079 uint32 level = q_u->level;
8080 RPC_BUFFER *buffer = NULL;
8081 uint32 offered = q_u->offered;
8082 uint32 *needed = &r_u->needed;
8084 /* that's an [in out] buffer */
8086 if (!q_u->buffer && (offered!=0)) {
8087 return WERR_INVALID_PARAM;
8090 rpcbuf_move(q_u->buffer, &r_u->buffer);
8091 buffer = r_u->buffer;
8093 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8095 *needed=0;
8097 switch(level) {
8098 case 1:
8099 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8100 default:
8101 return WERR_UNKNOWN_LEVEL;
8105 /****************************************************************************
8106 ****************************************************************************/
8108 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8110 POLICY_HND *handle = &q_u->handle;
8111 uint32 idx = q_u->index;
8112 uint32 in_value_len = q_u->valuesize;
8113 uint32 in_data_len = q_u->datasize;
8114 uint32 *out_max_value_len = &r_u->valuesize;
8115 uint16 **out_value = &r_u->value;
8116 uint32 *out_value_len = &r_u->realvaluesize;
8117 uint32 *out_type = &r_u->type;
8118 uint32 *out_max_data_len = &r_u->datasize;
8119 uint8 **data_out = &r_u->data;
8120 uint32 *out_data_len = &r_u->realdatasize;
8122 NT_PRINTER_INFO_LEVEL *printer = NULL;
8124 uint32 biggest_valuesize;
8125 uint32 biggest_datasize;
8126 uint32 data_len;
8127 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8128 int snum;
8129 WERROR result;
8130 REGISTRY_VALUE *val = NULL;
8131 NT_PRINTER_DATA *p_data;
8132 int i, key_index, num_values;
8133 int name_length;
8135 *out_type = 0;
8137 *out_max_data_len = 0;
8138 *data_out = NULL;
8139 *out_data_len = 0;
8141 DEBUG(5,("spoolss_enumprinterdata\n"));
8143 if (!Printer) {
8144 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8145 return WERR_BADFID;
8148 if (!get_printer_snum(p,handle, &snum, NULL))
8149 return WERR_BADFID;
8151 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8152 if (!W_ERROR_IS_OK(result))
8153 return result;
8155 p_data = printer->info_2->data;
8156 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8158 result = WERR_OK;
8161 * The NT machine wants to know the biggest size of value and data
8163 * cf: MSDN EnumPrinterData remark section
8166 if ( !in_value_len && !in_data_len && (key_index != -1) )
8168 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8170 biggest_valuesize = 0;
8171 biggest_datasize = 0;
8173 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8175 for ( i=0; i<num_values; i++ )
8177 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8179 name_length = strlen(val->valuename);
8180 if ( strlen(val->valuename) > biggest_valuesize )
8181 biggest_valuesize = name_length;
8183 if ( val->size > biggest_datasize )
8184 biggest_datasize = val->size;
8186 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8187 biggest_datasize));
8190 /* the value is an UNICODE string but real_value_size is the length
8191 in bytes including the trailing 0 */
8193 *out_value_len = 2 * (1+biggest_valuesize);
8194 *out_data_len = biggest_datasize;
8196 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8198 goto done;
8202 * the value len is wrong in NT sp3
8203 * that's the number of bytes not the number of unicode chars
8206 if ( key_index != -1 )
8207 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8209 if ( !val )
8212 /* out_value should default to "" or else NT4 has
8213 problems unmarshalling the response */
8215 *out_max_value_len=(in_value_len/sizeof(uint16));
8217 if (in_value_len) {
8218 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8220 result = WERR_NOMEM;
8221 goto done;
8223 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8224 } else {
8225 *out_value=NULL;
8226 *out_value_len = 0;
8229 /* the data is counted in bytes */
8231 *out_max_data_len = in_data_len;
8232 *out_data_len = in_data_len;
8234 /* only allocate when given a non-zero data_len */
8236 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8238 result = WERR_NOMEM;
8239 goto done;
8242 result = WERR_NO_MORE_ITEMS;
8244 else
8247 * the value is:
8248 * - counted in bytes in the request
8249 * - counted in UNICODE chars in the max reply
8250 * - counted in bytes in the real size
8252 * take a pause *before* coding not *during* coding
8255 /* name */
8256 *out_max_value_len=(in_value_len/sizeof(uint16));
8257 if (in_value_len) {
8258 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8260 result = WERR_NOMEM;
8261 goto done;
8264 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8265 } else {
8266 *out_value = NULL;
8267 *out_value_len = 0;
8270 /* type */
8272 *out_type = regval_type( val );
8274 /* data - counted in bytes */
8276 *out_max_data_len = in_data_len;
8277 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8279 result = WERR_NOMEM;
8280 goto done;
8282 data_len = regval_size(val);
8283 if ( *data_out && data_len )
8284 memcpy( *data_out, regval_data_p(val), data_len );
8285 *out_data_len = data_len;
8288 done:
8289 free_a_printer(&printer, 2);
8290 return result;
8293 /****************************************************************************
8294 ****************************************************************************/
8296 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8298 POLICY_HND *handle = &q_u->handle;
8299 UNISTR2 *value = &q_u->value;
8300 uint32 type = q_u->type;
8301 uint8 *data = q_u->data;
8302 uint32 real_len = q_u->real_len;
8304 NT_PRINTER_INFO_LEVEL *printer = NULL;
8305 int snum=0;
8306 WERROR status = WERR_OK;
8307 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8308 fstring valuename;
8310 DEBUG(5,("spoolss_setprinterdata\n"));
8312 if (!Printer) {
8313 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8314 return WERR_BADFID;
8317 if ( Printer->printer_type == SPLHND_SERVER ) {
8318 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8319 return WERR_INVALID_PARAM;
8322 if (!get_printer_snum(p,handle, &snum, NULL))
8323 return WERR_BADFID;
8326 * Access check : NT returns "access denied" if you make a
8327 * SetPrinterData call without the necessary privildge.
8328 * we were originally returning OK if nothing changed
8329 * which made Win2k issue **a lot** of SetPrinterData
8330 * when connecting to a printer --jerry
8333 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8335 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8336 status = WERR_ACCESS_DENIED;
8337 goto done;
8340 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8341 if (!W_ERROR_IS_OK(status))
8342 return status;
8344 unistr2_to_ascii(valuename, value, sizeof(valuename));
8347 * When client side code sets a magic printer data key, detect it and save
8348 * the current printer data and the magic key's data (its the DEVMODE) for
8349 * future printer/driver initializations.
8351 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8353 /* Set devmode and printer initialization info */
8354 status = save_driver_init( printer, 2, data, real_len );
8356 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8358 else
8360 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8361 type, data, real_len );
8362 if ( W_ERROR_IS_OK(status) )
8363 status = mod_a_printer(printer, 2);
8366 done:
8367 free_a_printer(&printer, 2);
8369 return status;
8372 /****************************************************************************
8373 ****************************************************************************/
8375 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8377 POLICY_HND *handle = &q_u->handle;
8378 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8379 int snum;
8381 DEBUG(5,("_spoolss_resetprinter\n"));
8384 * All we do is to check to see if the handle and queue is valid.
8385 * This call really doesn't mean anything to us because we only
8386 * support RAW printing. --jerry
8389 if (!Printer) {
8390 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8391 return WERR_BADFID;
8394 if (!get_printer_snum(p,handle, &snum, NULL))
8395 return WERR_BADFID;
8398 /* blindly return success */
8399 return WERR_OK;
8403 /****************************************************************************
8404 ****************************************************************************/
8406 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8408 POLICY_HND *handle = &q_u->handle;
8409 UNISTR2 *value = &q_u->valuename;
8411 NT_PRINTER_INFO_LEVEL *printer = NULL;
8412 int snum=0;
8413 WERROR status = WERR_OK;
8414 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8415 char *valuename = NULL;
8416 TALLOC_CTX *ctx = p->mem_ctx;
8418 DEBUG(5,("spoolss_deleteprinterdata\n"));
8420 if (!Printer) {
8421 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8422 return WERR_BADFID;
8425 if (!get_printer_snum(p, handle, &snum, NULL))
8426 return WERR_BADFID;
8428 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8429 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8430 return WERR_ACCESS_DENIED;
8433 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8434 if (!W_ERROR_IS_OK(status))
8435 return status;
8437 valuename = unistr2_to_ascii_talloc(ctx, value);
8438 if (!valuename) {
8439 free_a_printer(&printer, 2);
8440 return WERR_NOMEM;
8443 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8445 if ( W_ERROR_IS_OK(status) )
8446 mod_a_printer( printer, 2 );
8448 free_a_printer(&printer, 2);
8449 TALLOC_FREE(valuename);
8451 return status;
8454 /****************************************************************************
8455 ****************************************************************************/
8457 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8459 POLICY_HND *handle = &q_u->handle;
8460 FORM *form = &q_u->form;
8461 nt_forms_struct tmpForm;
8462 int snum;
8463 WERROR status = WERR_OK;
8464 NT_PRINTER_INFO_LEVEL *printer = NULL;
8466 int count=0;
8467 nt_forms_struct *list=NULL;
8468 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8470 DEBUG(5,("spoolss_addform\n"));
8472 if (!Printer) {
8473 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8474 return WERR_BADFID;
8478 /* forms can be added on printer of on the print server handle */
8480 if ( Printer->printer_type == SPLHND_PRINTER )
8482 if (!get_printer_snum(p,handle, &snum, NULL))
8483 return WERR_BADFID;
8485 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8486 if (!W_ERROR_IS_OK(status))
8487 goto done;
8490 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8491 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8492 status = WERR_ACCESS_DENIED;
8493 goto done;
8496 /* can't add if builtin */
8498 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8499 status = WERR_FILE_EXISTS;
8500 goto done;
8503 count = get_ntforms(&list);
8505 if(!add_a_form(&list, form, &count)) {
8506 status = WERR_NOMEM;
8507 goto done;
8510 write_ntforms(&list, count);
8513 * ChangeID must always be set if this is a printer
8516 if ( Printer->printer_type == SPLHND_PRINTER )
8517 status = mod_a_printer(printer, 2);
8519 done:
8520 if ( printer )
8521 free_a_printer(&printer, 2);
8522 SAFE_FREE(list);
8524 return status;
8527 /****************************************************************************
8528 ****************************************************************************/
8530 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8532 POLICY_HND *handle = &q_u->handle;
8533 UNISTR2 *form_name = &q_u->name;
8534 nt_forms_struct tmpForm;
8535 int count=0;
8536 nt_forms_struct *list=NULL;
8537 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8538 int snum;
8539 WERROR status = WERR_OK;
8540 NT_PRINTER_INFO_LEVEL *printer = NULL;
8542 DEBUG(5,("spoolss_deleteform\n"));
8544 if (!Printer) {
8545 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8546 return WERR_BADFID;
8549 /* forms can be deleted on printer of on the print server handle */
8551 if ( Printer->printer_type == SPLHND_PRINTER )
8553 if (!get_printer_snum(p,handle, &snum, NULL))
8554 return WERR_BADFID;
8556 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8557 if (!W_ERROR_IS_OK(status))
8558 goto done;
8561 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8562 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8563 status = WERR_ACCESS_DENIED;
8564 goto done;
8567 /* can't delete if builtin */
8569 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8570 status = WERR_INVALID_PARAM;
8571 goto done;
8574 count = get_ntforms(&list);
8576 if ( !delete_a_form(&list, form_name, &count, &status ))
8577 goto done;
8580 * ChangeID must always be set if this is a printer
8583 if ( Printer->printer_type == SPLHND_PRINTER )
8584 status = mod_a_printer(printer, 2);
8586 done:
8587 if ( printer )
8588 free_a_printer(&printer, 2);
8589 SAFE_FREE(list);
8591 return status;
8594 /****************************************************************************
8595 ****************************************************************************/
8597 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8599 POLICY_HND *handle = &q_u->handle;
8600 FORM *form = &q_u->form;
8601 nt_forms_struct tmpForm;
8602 int snum;
8603 WERROR status = WERR_OK;
8604 NT_PRINTER_INFO_LEVEL *printer = NULL;
8606 int count=0;
8607 nt_forms_struct *list=NULL;
8608 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8610 DEBUG(5,("spoolss_setform\n"));
8612 if (!Printer) {
8613 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8614 return WERR_BADFID;
8617 /* forms can be modified on printer of on the print server handle */
8619 if ( Printer->printer_type == SPLHND_PRINTER )
8621 if (!get_printer_snum(p,handle, &snum, NULL))
8622 return WERR_BADFID;
8624 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8625 if (!W_ERROR_IS_OK(status))
8626 goto done;
8629 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8630 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8631 status = WERR_ACCESS_DENIED;
8632 goto done;
8635 /* can't set if builtin */
8636 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8637 status = WERR_INVALID_PARAM;
8638 goto done;
8641 count = get_ntforms(&list);
8642 update_a_form(&list, form, count);
8643 write_ntforms(&list, count);
8646 * ChangeID must always be set if this is a printer
8649 if ( Printer->printer_type == SPLHND_PRINTER )
8650 status = mod_a_printer(printer, 2);
8653 done:
8654 if ( printer )
8655 free_a_printer(&printer, 2);
8656 SAFE_FREE(list);
8658 return status;
8661 /****************************************************************************
8662 enumprintprocessors level 1.
8663 ****************************************************************************/
8665 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8667 PRINTPROCESSOR_1 *info_1=NULL;
8668 WERROR result = WERR_OK;
8670 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8671 return WERR_NOMEM;
8673 (*returned) = 0x1;
8675 init_unistr(&info_1->name, "winprint");
8677 *needed += spoolss_size_printprocessor_info_1(info_1);
8679 if (*needed > offered) {
8680 result = WERR_INSUFFICIENT_BUFFER;
8681 goto out;
8684 if (!rpcbuf_alloc_size(buffer, *needed)) {
8685 result = WERR_NOMEM;
8686 goto out;
8689 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8691 out:
8692 SAFE_FREE(info_1);
8694 if ( !W_ERROR_IS_OK(result) )
8695 *returned = 0;
8697 return result;
8700 /****************************************************************************
8701 ****************************************************************************/
8703 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8705 uint32 level = q_u->level;
8706 RPC_BUFFER *buffer = NULL;
8707 uint32 offered = q_u->offered;
8708 uint32 *needed = &r_u->needed;
8709 uint32 *returned = &r_u->returned;
8711 /* that's an [in out] buffer */
8713 if (!q_u->buffer && (offered!=0)) {
8714 return WERR_INVALID_PARAM;
8717 rpcbuf_move(q_u->buffer, &r_u->buffer);
8718 buffer = r_u->buffer;
8720 DEBUG(5,("spoolss_enumprintprocessors\n"));
8723 * Enumerate the print processors ...
8725 * Just reply with "winprint", to keep NT happy
8726 * and I can use my nice printer checker.
8729 *returned=0;
8730 *needed=0;
8732 switch (level) {
8733 case 1:
8734 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8735 default:
8736 return WERR_UNKNOWN_LEVEL;
8740 /****************************************************************************
8741 enumprintprocdatatypes level 1.
8742 ****************************************************************************/
8744 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8746 PRINTPROCDATATYPE_1 *info_1=NULL;
8747 WERROR result = WERR_OK;
8749 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8750 return WERR_NOMEM;
8752 (*returned) = 0x1;
8754 init_unistr(&info_1->name, "RAW");
8756 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8758 if (*needed > offered) {
8759 result = WERR_INSUFFICIENT_BUFFER;
8760 goto out;
8763 if (!rpcbuf_alloc_size(buffer, *needed)) {
8764 result = WERR_NOMEM;
8765 goto out;
8768 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8770 out:
8771 SAFE_FREE(info_1);
8773 if ( !W_ERROR_IS_OK(result) )
8774 *returned = 0;
8776 return result;
8779 /****************************************************************************
8780 ****************************************************************************/
8782 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8784 uint32 level = q_u->level;
8785 RPC_BUFFER *buffer = NULL;
8786 uint32 offered = q_u->offered;
8787 uint32 *needed = &r_u->needed;
8788 uint32 *returned = &r_u->returned;
8790 /* that's an [in out] buffer */
8792 if (!q_u->buffer && (offered!=0)) {
8793 return WERR_INVALID_PARAM;
8796 rpcbuf_move(q_u->buffer, &r_u->buffer);
8797 buffer = r_u->buffer;
8799 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8801 *returned=0;
8802 *needed=0;
8804 switch (level) {
8805 case 1:
8806 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8807 default:
8808 return WERR_UNKNOWN_LEVEL;
8812 /****************************************************************************
8813 enumprintmonitors level 1.
8814 ****************************************************************************/
8816 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8818 PRINTMONITOR_1 *info_1;
8819 WERROR result = WERR_OK;
8820 int i;
8822 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8823 return WERR_NOMEM;
8825 *returned = 2;
8827 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8828 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8830 for ( i=0; i<*returned; i++ ) {
8831 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8834 if (*needed > offered) {
8835 result = WERR_INSUFFICIENT_BUFFER;
8836 goto out;
8839 if (!rpcbuf_alloc_size(buffer, *needed)) {
8840 result = WERR_NOMEM;
8841 goto out;
8844 for ( i=0; i<*returned; i++ ) {
8845 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8848 out:
8849 SAFE_FREE(info_1);
8851 if ( !W_ERROR_IS_OK(result) )
8852 *returned = 0;
8854 return result;
8857 /****************************************************************************
8858 enumprintmonitors level 2.
8859 ****************************************************************************/
8861 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8863 PRINTMONITOR_2 *info_2;
8864 WERROR result = WERR_OK;
8865 int i;
8867 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8868 return WERR_NOMEM;
8870 *returned = 2;
8872 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8873 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8874 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8876 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8877 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8878 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8880 for ( i=0; i<*returned; i++ ) {
8881 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8884 if (*needed > offered) {
8885 result = WERR_INSUFFICIENT_BUFFER;
8886 goto out;
8889 if (!rpcbuf_alloc_size(buffer, *needed)) {
8890 result = WERR_NOMEM;
8891 goto out;
8894 for ( i=0; i<*returned; i++ ) {
8895 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8898 out:
8899 SAFE_FREE(info_2);
8901 if ( !W_ERROR_IS_OK(result) )
8902 *returned = 0;
8904 return result;
8907 /****************************************************************************
8908 ****************************************************************************/
8910 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8912 uint32 level = q_u->level;
8913 RPC_BUFFER *buffer = NULL;
8914 uint32 offered = q_u->offered;
8915 uint32 *needed = &r_u->needed;
8916 uint32 *returned = &r_u->returned;
8918 /* that's an [in out] buffer */
8920 if (!q_u->buffer && (offered!=0)) {
8921 return WERR_INVALID_PARAM;
8924 rpcbuf_move(q_u->buffer, &r_u->buffer);
8925 buffer = r_u->buffer;
8927 DEBUG(5,("spoolss_enumprintmonitors\n"));
8930 * Enumerate the print monitors ...
8932 * Just reply with "Local Port", to keep NT happy
8933 * and I can use my nice printer checker.
8936 *returned=0;
8937 *needed=0;
8939 switch (level) {
8940 case 1:
8941 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8942 case 2:
8943 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8944 default:
8945 return WERR_UNKNOWN_LEVEL;
8949 /****************************************************************************
8950 ****************************************************************************/
8952 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8953 NT_PRINTER_INFO_LEVEL *ntprinter,
8954 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8955 uint32 *needed)
8957 int i=0;
8958 bool found=False;
8959 JOB_INFO_1 *info_1=NULL;
8960 WERROR result = WERR_OK;
8962 info_1=SMB_MALLOC_P(JOB_INFO_1);
8964 if (info_1 == NULL) {
8965 return WERR_NOMEM;
8968 for (i=0; i<count && found==False; i++) {
8969 if ((*queue)[i].job==(int)jobid)
8970 found=True;
8973 if (found==False) {
8974 SAFE_FREE(info_1);
8975 /* NT treats not found as bad param... yet another bad choice */
8976 return WERR_INVALID_PARAM;
8979 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8981 *needed += spoolss_size_job_info_1(info_1);
8983 if (*needed > offered) {
8984 result = WERR_INSUFFICIENT_BUFFER;
8985 goto out;
8988 if (!rpcbuf_alloc_size(buffer, *needed)) {
8989 result = WERR_NOMEM;
8990 goto out;
8993 smb_io_job_info_1("", buffer, info_1, 0);
8995 out:
8996 SAFE_FREE(info_1);
8998 return result;
9001 /****************************************************************************
9002 ****************************************************************************/
9004 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9005 NT_PRINTER_INFO_LEVEL *ntprinter,
9006 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9007 uint32 *needed)
9009 int i = 0;
9010 bool found = False;
9011 JOB_INFO_2 *info_2;
9012 WERROR result;
9013 DEVICEMODE *devmode = NULL;
9014 NT_DEVICEMODE *nt_devmode = NULL;
9016 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9017 return WERR_NOMEM;
9019 ZERO_STRUCTP(info_2);
9021 for ( i=0; i<count && found==False; i++ )
9023 if ((*queue)[i].job == (int)jobid)
9024 found = True;
9027 if ( !found ) {
9028 /* NT treats not found as bad param... yet another bad
9029 choice */
9030 result = WERR_INVALID_PARAM;
9031 goto done;
9035 * if the print job does not have a DEVMODE associated with it,
9036 * just use the one for the printer. A NULL devicemode is not
9037 * a failure condition
9040 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9041 devmode = construct_dev_mode(lp_const_servicename(snum));
9042 else {
9043 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9044 ZERO_STRUCTP( devmode );
9045 convert_nt_devicemode( devmode, nt_devmode );
9049 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9051 *needed += spoolss_size_job_info_2(info_2);
9053 if (*needed > offered) {
9054 result = WERR_INSUFFICIENT_BUFFER;
9055 goto done;
9058 if (!rpcbuf_alloc_size(buffer, *needed)) {
9059 result = WERR_NOMEM;
9060 goto done;
9063 smb_io_job_info_2("", buffer, info_2, 0);
9065 result = WERR_OK;
9067 done:
9068 /* Cleanup allocated memory */
9070 free_job_info_2(info_2); /* Also frees devmode */
9071 SAFE_FREE(info_2);
9073 return result;
9076 /****************************************************************************
9077 ****************************************************************************/
9079 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9081 POLICY_HND *handle = &q_u->handle;
9082 uint32 jobid = q_u->jobid;
9083 uint32 level = q_u->level;
9084 RPC_BUFFER *buffer = NULL;
9085 uint32 offered = q_u->offered;
9086 uint32 *needed = &r_u->needed;
9087 WERROR wstatus = WERR_OK;
9088 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9089 int snum;
9090 int count;
9091 print_queue_struct *queue = NULL;
9092 print_status_struct prt_status;
9094 /* that's an [in out] buffer */
9096 if (!q_u->buffer && (offered!=0)) {
9097 return WERR_INVALID_PARAM;
9100 rpcbuf_move(q_u->buffer, &r_u->buffer);
9101 buffer = r_u->buffer;
9103 DEBUG(5,("spoolss_getjob\n"));
9105 *needed = 0;
9107 if (!get_printer_snum(p, handle, &snum, NULL))
9108 return WERR_BADFID;
9110 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9111 if ( !W_ERROR_IS_OK(wstatus) )
9112 return wstatus;
9114 count = print_queue_status(snum, &queue, &prt_status);
9116 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9117 count, prt_status.status, prt_status.message));
9119 switch ( level ) {
9120 case 1:
9121 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9122 buffer, offered, needed);
9123 break;
9124 case 2:
9125 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9126 buffer, offered, needed);
9127 break;
9128 default:
9129 wstatus = WERR_UNKNOWN_LEVEL;
9130 break;
9133 SAFE_FREE(queue);
9134 free_a_printer( &ntprinter, 2 );
9136 return wstatus;
9139 /********************************************************************
9140 spoolss_getprinterdataex
9142 From MSDN documentation of GetPrinterDataEx: pass request
9143 to GetPrinterData if key is "PrinterDriverData".
9144 ********************************************************************/
9146 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9148 POLICY_HND *handle = &q_u->handle;
9149 uint32 in_size = q_u->size;
9150 uint32 *type = &r_u->type;
9151 uint32 *out_size = &r_u->size;
9152 uint8 **data = &r_u->data;
9153 uint32 *needed = &r_u->needed;
9154 fstring keyname, valuename;
9156 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9158 NT_PRINTER_INFO_LEVEL *printer = NULL;
9159 int snum = 0;
9160 WERROR status = WERR_OK;
9162 DEBUG(4,("_spoolss_getprinterdataex\n"));
9164 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9165 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9167 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9168 keyname, valuename));
9170 /* in case of problem, return some default values */
9172 *needed = 0;
9173 *type = 0;
9174 *out_size = in_size;
9176 if (!Printer) {
9177 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9178 status = WERR_BADFID;
9179 goto done;
9182 /* Is the handle to a printer or to the server? */
9184 if (Printer->printer_type == SPLHND_SERVER) {
9185 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9186 status = WERR_INVALID_PARAM;
9187 goto done;
9190 if ( !get_printer_snum(p,handle, &snum, NULL) )
9191 return WERR_BADFID;
9193 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9194 if ( !W_ERROR_IS_OK(status) )
9195 goto done;
9197 /* check to see if the keyname is valid */
9198 if ( !strlen(keyname) ) {
9199 status = WERR_INVALID_PARAM;
9200 goto done;
9203 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9204 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9205 free_a_printer( &printer, 2 );
9206 status = WERR_BADFILE;
9207 goto done;
9210 /* When given a new keyname, we should just create it */
9212 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9214 if (*needed > *out_size)
9215 status = WERR_MORE_DATA;
9217 done:
9218 if ( !W_ERROR_IS_OK(status) )
9220 DEBUG(5, ("error: allocating %d\n", *out_size));
9222 /* reply this param doesn't exist */
9224 if ( *out_size )
9226 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9227 status = WERR_NOMEM;
9228 goto done;
9230 } else {
9231 *data = NULL;
9235 if ( printer )
9236 free_a_printer( &printer, 2 );
9238 return status;
9241 /********************************************************************
9242 * spoolss_setprinterdataex
9243 ********************************************************************/
9245 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9247 POLICY_HND *handle = &q_u->handle;
9248 uint32 type = q_u->type;
9249 uint8 *data = q_u->data;
9250 uint32 real_len = q_u->real_len;
9252 NT_PRINTER_INFO_LEVEL *printer = NULL;
9253 int snum = 0;
9254 WERROR status = WERR_OK;
9255 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9256 fstring valuename;
9257 fstring keyname;
9258 char *oid_string;
9260 DEBUG(4,("_spoolss_setprinterdataex\n"));
9262 /* From MSDN documentation of SetPrinterDataEx: pass request to
9263 SetPrinterData if key is "PrinterDriverData" */
9265 if (!Printer) {
9266 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9267 return WERR_BADFID;
9270 if ( Printer->printer_type == SPLHND_SERVER ) {
9271 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9272 return WERR_INVALID_PARAM;
9275 if ( !get_printer_snum(p,handle, &snum, NULL) )
9276 return WERR_BADFID;
9279 * Access check : NT returns "access denied" if you make a
9280 * SetPrinterData call without the necessary privildge.
9281 * we were originally returning OK if nothing changed
9282 * which made Win2k issue **a lot** of SetPrinterData
9283 * when connecting to a printer --jerry
9286 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9288 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9289 return WERR_ACCESS_DENIED;
9292 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9293 if (!W_ERROR_IS_OK(status))
9294 return status;
9296 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9297 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9299 /* check for OID in valuename */
9301 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9303 *oid_string = '\0';
9304 oid_string++;
9307 /* save the registry data */
9309 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9311 if ( W_ERROR_IS_OK(status) )
9313 /* save the OID if one was specified */
9314 if ( oid_string ) {
9315 fstrcat( keyname, "\\" );
9316 fstrcat( keyname, SPOOL_OID_KEY );
9319 * I'm not checking the status here on purpose. Don't know
9320 * if this is right, but I'm returning the status from the
9321 * previous set_printer_dataex() call. I have no idea if
9322 * this is right. --jerry
9325 set_printer_dataex( printer, keyname, valuename,
9326 REG_SZ, (uint8 *)oid_string,
9327 strlen(oid_string)+1 );
9330 status = mod_a_printer(printer, 2);
9333 free_a_printer(&printer, 2);
9335 return status;
9339 /********************************************************************
9340 * spoolss_deleteprinterdataex
9341 ********************************************************************/
9343 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9345 POLICY_HND *handle = &q_u->handle;
9346 UNISTR2 *value = &q_u->valuename;
9347 UNISTR2 *key = &q_u->keyname;
9349 NT_PRINTER_INFO_LEVEL *printer = NULL;
9350 int snum=0;
9351 WERROR status = WERR_OK;
9352 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9353 char *valuename = NULL;
9354 char *keyname = NULL;
9355 TALLOC_CTX *ctx = p->mem_ctx;
9357 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9359 if (!Printer) {
9360 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9361 return WERR_BADFID;
9364 if (!get_printer_snum(p, handle, &snum, NULL))
9365 return WERR_BADFID;
9367 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9368 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9369 return WERR_ACCESS_DENIED;
9372 valuename = unistr2_to_ascii_talloc(ctx, value);
9373 keyname = unistr2_to_ascii_talloc(ctx, key);
9374 if (!valuename || !keyname) {
9375 return WERR_NOMEM;
9378 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9379 if (!W_ERROR_IS_OK(status))
9380 return status;
9382 status = delete_printer_dataex( printer, keyname, valuename );
9384 if ( W_ERROR_IS_OK(status) )
9385 mod_a_printer( printer, 2 );
9387 free_a_printer(&printer, 2);
9389 return status;
9392 /********************************************************************
9393 * spoolss_enumprinterkey
9394 ********************************************************************/
9397 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9399 fstring key;
9400 fstring *keynames = NULL;
9401 uint16 *enumkeys = NULL;
9402 int num_keys;
9403 int printerkey_len;
9404 POLICY_HND *handle = &q_u->handle;
9405 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9406 NT_PRINTER_DATA *data;
9407 NT_PRINTER_INFO_LEVEL *printer = NULL;
9408 int snum = 0;
9409 WERROR status = WERR_BADFILE;
9412 DEBUG(4,("_spoolss_enumprinterkey\n"));
9414 if (!Printer) {
9415 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9416 return WERR_BADFID;
9419 if ( !get_printer_snum(p,handle, &snum, NULL) )
9420 return WERR_BADFID;
9422 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9423 if (!W_ERROR_IS_OK(status))
9424 return status;
9426 /* get the list of subkey names */
9428 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9429 data = printer->info_2->data;
9431 num_keys = get_printer_subkeys( data, key, &keynames );
9433 if ( num_keys == -1 ) {
9434 status = WERR_BADFILE;
9435 goto done;
9438 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9440 r_u->needed = printerkey_len*2;
9442 if ( q_u->size < r_u->needed ) {
9443 status = WERR_MORE_DATA;
9444 goto done;
9447 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9448 status = WERR_NOMEM;
9449 goto done;
9452 status = WERR_OK;
9454 if ( q_u->size < r_u->needed )
9455 status = WERR_MORE_DATA;
9457 done:
9458 free_a_printer( &printer, 2 );
9459 SAFE_FREE( keynames );
9461 return status;
9464 /********************************************************************
9465 * spoolss_deleteprinterkey
9466 ********************************************************************/
9468 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9470 POLICY_HND *handle = &q_u->handle;
9471 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9472 fstring key;
9473 NT_PRINTER_INFO_LEVEL *printer = NULL;
9474 int snum=0;
9475 WERROR status;
9477 DEBUG(5,("spoolss_deleteprinterkey\n"));
9479 if (!Printer) {
9480 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9481 return WERR_BADFID;
9484 /* if keyname == NULL, return error */
9486 if ( !q_u->keyname.buffer )
9487 return WERR_INVALID_PARAM;
9489 if (!get_printer_snum(p, handle, &snum, NULL))
9490 return WERR_BADFID;
9492 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9493 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9494 return WERR_ACCESS_DENIED;
9497 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9498 if (!W_ERROR_IS_OK(status))
9499 return status;
9501 /* delete the key and all subneys */
9503 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9505 status = delete_all_printer_data( printer->info_2, key );
9507 if ( W_ERROR_IS_OK(status) )
9508 status = mod_a_printer(printer, 2);
9510 free_a_printer( &printer, 2 );
9512 return status;
9516 /********************************************************************
9517 * spoolss_enumprinterdataex
9518 ********************************************************************/
9520 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9522 POLICY_HND *handle = &q_u->handle;
9523 uint32 in_size = q_u->size;
9524 uint32 num_entries,
9525 needed;
9526 NT_PRINTER_INFO_LEVEL *printer = NULL;
9527 PRINTER_ENUM_VALUES *enum_values = NULL;
9528 NT_PRINTER_DATA *p_data;
9529 fstring key;
9530 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9531 int snum;
9532 WERROR result;
9533 int key_index;
9534 int i;
9535 REGISTRY_VALUE *val;
9536 char *value_name;
9537 uint32 data_len;
9540 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9542 if (!Printer) {
9543 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9544 return WERR_BADFID;
9548 * first check for a keyname of NULL or "". Win2k seems to send
9549 * this a lot and we should send back WERR_INVALID_PARAM
9550 * no need to spend time looking up the printer in this case.
9551 * --jerry
9554 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9555 if ( !strlen(key) ) {
9556 result = WERR_INVALID_PARAM;
9557 goto done;
9560 /* get the printer off of disk */
9562 if (!get_printer_snum(p,handle, &snum, NULL))
9563 return WERR_BADFID;
9565 ZERO_STRUCT(printer);
9566 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9567 if (!W_ERROR_IS_OK(result))
9568 return result;
9570 /* now look for a match on the key name */
9572 p_data = printer->info_2->data;
9574 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9575 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9577 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9578 result = WERR_INVALID_PARAM;
9579 goto done;
9582 result = WERR_OK;
9583 needed = 0;
9585 /* allocate the memory for the array of pointers -- if necessary */
9587 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9588 if ( num_entries )
9590 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9592 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9593 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9594 result = WERR_NOMEM;
9595 goto done;
9598 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9602 * loop through all params and build the array to pass
9603 * back to the client
9606 for ( i=0; i<num_entries; i++ )
9608 /* lookup the registry value */
9610 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9611 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9613 /* copy the data */
9615 value_name = regval_name( val );
9616 init_unistr( &enum_values[i].valuename, value_name );
9617 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9618 enum_values[i].type = regval_type( val );
9620 data_len = regval_size( val );
9621 if ( data_len ) {
9622 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9624 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9625 data_len ));
9626 result = WERR_NOMEM;
9627 goto done;
9630 enum_values[i].data_len = data_len;
9632 /* keep track of the size of the array in bytes */
9634 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9637 /* housekeeping information in the reply */
9639 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9640 * the hand marshalled container size is a multiple
9641 * of 4 bytes for RPC alignment.
9644 if (needed % 4) {
9645 needed += 4-(needed % 4);
9648 r_u->needed = needed;
9649 r_u->returned = num_entries;
9651 if (needed > in_size) {
9652 result = WERR_MORE_DATA;
9653 goto done;
9656 /* copy data into the reply */
9658 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9659 response buffer size is != the offered buffer size
9661 r_u->ctr.size = r_u->needed;
9663 r_u->ctr.size = in_size;
9665 r_u->ctr.size_of_array = r_u->returned;
9666 r_u->ctr.values = enum_values;
9668 done:
9669 if ( printer )
9670 free_a_printer(&printer, 2);
9672 return result;
9675 /****************************************************************************
9676 ****************************************************************************/
9678 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9680 init_unistr(&info->name, name);
9683 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9684 UNISTR2 *environment,
9685 RPC_BUFFER *buffer,
9686 uint32 offered,
9687 uint32 *needed)
9689 char *long_archi = NULL;
9690 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9691 WERROR result = WERR_OK;
9692 TALLOC_CTX *ctx = talloc_tos();
9694 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9695 if (!long_archi) {
9696 return WERR_NOMEM;
9699 if (!get_short_archi(long_archi))
9700 return WERR_INVALID_ENVIRONMENT;
9702 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9703 return WERR_NOMEM;
9705 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9707 *needed += spoolss_size_printprocessordirectory_info_1(info);
9709 if (*needed > offered) {
9710 result = WERR_INSUFFICIENT_BUFFER;
9711 goto out;
9714 if (!rpcbuf_alloc_size(buffer, *needed)) {
9715 result = WERR_INSUFFICIENT_BUFFER;
9716 goto out;
9719 smb_io_printprocessordirectory_1("", buffer, info, 0);
9721 out:
9722 SAFE_FREE(info);
9724 return result;
9727 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9729 uint32 level = q_u->level;
9730 RPC_BUFFER *buffer = NULL;
9731 uint32 offered = q_u->offered;
9732 uint32 *needed = &r_u->needed;
9733 WERROR result;
9735 /* that's an [in out] buffer */
9737 if (!q_u->buffer && (offered!=0)) {
9738 return WERR_INVALID_PARAM;
9741 rpcbuf_move(q_u->buffer, &r_u->buffer);
9742 buffer = r_u->buffer;
9744 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9746 *needed=0;
9748 switch(level) {
9749 case 1:
9750 result = getprintprocessordirectory_level_1
9751 (&q_u->name, &q_u->environment, buffer, offered, needed);
9752 break;
9753 default:
9754 result = WERR_UNKNOWN_LEVEL;
9757 return result;
9760 /*******************************************************************
9761 Streams the monitor UI DLL name in UNICODE
9762 *******************************************************************/
9764 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9765 RPC_BUFFER *out, uint32 *needed )
9767 const char *dllname = "tcpmonui.dll";
9769 *needed = (strlen(dllname)+1) * 2;
9771 if ( rpcbuf_get_size(out) < *needed ) {
9772 return WERR_INSUFFICIENT_BUFFER;
9775 if ( !make_monitorui_buf( out, dllname ) ) {
9776 return WERR_NOMEM;
9779 return WERR_OK;
9782 /*******************************************************************
9783 Create a new TCP/IP port
9784 *******************************************************************/
9786 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9787 RPC_BUFFER *out, uint32 *needed )
9789 NT_PORT_DATA_1 port1;
9790 TALLOC_CTX *ctx = talloc_tos();
9791 char *device_uri = NULL;
9793 ZERO_STRUCT( port1 );
9795 /* convert to our internal port data structure */
9797 if ( !convert_port_data_1( &port1, in ) ) {
9798 return WERR_NOMEM;
9801 /* create the device URI and call the add_port_hook() */
9803 switch ( port1.protocol ) {
9804 case PORT_PROTOCOL_DIRECT:
9805 device_uri = talloc_asprintf(ctx,
9806 "socket://%s:%d/", port1.hostaddr, port1.port );
9807 break;
9809 case PORT_PROTOCOL_LPR:
9810 device_uri = talloc_asprintf(ctx,
9811 "lpr://%s/%s", port1.hostaddr, port1.queue );
9812 break;
9814 default:
9815 return WERR_UNKNOWN_PORT;
9818 if (!device_uri) {
9819 return WERR_NOMEM;
9822 return add_port_hook(ctx, token, port1.name, device_uri );
9825 /*******************************************************************
9826 *******************************************************************/
9828 struct xcv_api_table xcvtcp_cmds[] = {
9829 { "MonitorUI", xcvtcp_monitorui },
9830 { "AddPort", xcvtcp_addport},
9831 { NULL, NULL }
9834 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9835 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9836 uint32 *needed )
9838 int i;
9840 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9842 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9843 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9844 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9847 return WERR_BADFUNC;
9850 /*******************************************************************
9851 *******************************************************************/
9852 #if 0 /* don't support management using the "Local Port" monitor */
9854 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9855 RPC_BUFFER *out, uint32 *needed )
9857 const char *dllname = "localui.dll";
9859 *needed = (strlen(dllname)+1) * 2;
9861 if ( rpcbuf_get_size(out) < *needed ) {
9862 return WERR_INSUFFICIENT_BUFFER;
9865 if ( !make_monitorui_buf( out, dllname )) {
9866 return WERR_NOMEM;
9869 return WERR_OK;
9872 /*******************************************************************
9873 *******************************************************************/
9875 struct xcv_api_table xcvlocal_cmds[] = {
9876 { "MonitorUI", xcvlocal_monitorui },
9877 { NULL, NULL }
9879 #else
9880 struct xcv_api_table xcvlocal_cmds[] = {
9881 { NULL, NULL }
9883 #endif
9887 /*******************************************************************
9888 *******************************************************************/
9890 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9891 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9892 uint32 *needed )
9894 int i;
9896 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9898 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9899 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9900 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9902 return WERR_BADFUNC;
9905 /*******************************************************************
9906 *******************************************************************/
9908 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9910 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9911 fstring command;
9913 if (!Printer) {
9914 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9915 return WERR_BADFID;
9918 /* Has to be a handle to the TCP/IP port monitor */
9920 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9921 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9922 return WERR_BADFID;
9925 /* requires administrative access to the server */
9927 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9928 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9929 return WERR_ACCESS_DENIED;
9932 /* Get the command name. There's numerous commands supported by the
9933 TCPMON interface. */
9935 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9936 q_u->dataname.uni_str_len*2, 0);
9938 /* Allocate the outgoing buffer */
9940 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9942 switch ( Printer->printer_type ) {
9943 case SPLHND_PORTMON_TCP:
9944 return process_xcvtcp_command( p->server_info->ptok, command,
9945 &q_u->indata, &r_u->outdata, &r_u->needed );
9946 case SPLHND_PORTMON_LOCAL:
9947 return process_xcvlocal_command( p->server_info->ptok, command,
9948 &q_u->indata, &r_u->outdata, &r_u->needed );
9951 return WERR_INVALID_PRINT_MONITOR;