lib/tevent: expose ev_timeval_zero() for internal usage
[Samba/gbeck.git] / source3 / rpc_server / srv_spoolss_nt.c
blob7199441820915e5d8e33082d345f0200a1ce70d0
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;
153 NTSTATUS status;
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166 return;
169 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
170 handle,
171 &result);
172 if (!NT_STATUS_IS_OK(status) || !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 int printer_entry_destructor(Printer_entry *Printer)
200 if (Printer->notify.client_connected==True) {
201 int snum = -1;
203 if ( Printer->printer_type == SPLHND_SERVER) {
204 snum = -1;
205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206 } else if (Printer->printer_type == SPLHND_PRINTER) {
207 snum = print_queue_snum(Printer->sharename);
208 if (snum != -1)
209 srv_spoolss_replycloseprinter(snum,
210 &Printer->notify.client_hnd);
214 Printer->notify.flags=0;
215 Printer->notify.options=0;
216 Printer->notify.localmachine[0]='\0';
217 Printer->notify.printerlocal=0;
218 free_spool_notify_option(&Printer->notify.option);
219 Printer->notify.option=NULL;
220 Printer->notify.client_connected=False;
222 free_nt_devicemode( &Printer->nt_devmode );
223 free_a_printer( &Printer->printer_info, 2 );
225 /* Remove from the internal list. */
226 DLIST_REMOVE(printers_list, Printer);
227 return 0;
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
236 SPOOL_NOTIFY_OPTION *new_sp = NULL;
238 if (!sp)
239 return NULL;
241 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
242 if (!new_sp)
243 return NULL;
245 *new_sp = *sp;
247 if (sp->ctr.count) {
248 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
250 if (!new_sp->ctr.type) {
251 SAFE_FREE(new_sp);
252 return NULL;
256 return new_sp;
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
265 Printer_entry *find_printer = NULL;
267 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
269 return NULL;
272 return find_printer;
275 /****************************************************************************
276 Close printer index by handle.
277 ****************************************************************************/
279 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
281 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
283 if (!Printer) {
284 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
285 return False;
288 close_policy_hnd(p, hnd);
290 return True;
293 /****************************************************************************
294 Delete a printer given a handle.
295 ****************************************************************************/
297 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
299 char *cmd = lp_deleteprinter_cmd();
300 char *command = NULL;
301 int ret;
302 SE_PRIV se_printop = SE_PRINT_OPERATOR;
303 bool is_print_op = False;
305 /* can't fail if we don't try */
307 if ( !*cmd )
308 return WERR_OK;
310 command = talloc_asprintf(ctx,
311 "%s \"%s\"",
312 cmd, sharename);
313 if (!command) {
314 return WERR_NOMEM;
316 if ( token )
317 is_print_op = user_has_privileges( token, &se_printop );
319 DEBUG(10,("Running [%s]\n", command));
321 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
323 if ( is_print_op )
324 become_root();
326 if ( (ret = smbrun(command, NULL)) == 0 ) {
327 /* Tell everyone we updated smb.conf. */
328 message_send_all(smbd_messaging_context(),
329 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
332 if ( is_print_op )
333 unbecome_root();
335 /********** END SePrintOperatorPrivlege BLOCK **********/
337 DEBUGADD(10,("returned [%d]\n", ret));
339 TALLOC_FREE(command);
341 if (ret != 0)
342 return WERR_BADFID; /* What to return here? */
344 /* go ahead and re-read the services immediately */
345 reload_services( False );
347 if ( lp_servicenumber( sharename ) < 0 )
348 return WERR_ACCESS_DENIED;
350 return WERR_OK;
353 /****************************************************************************
354 Delete a printer given a handle.
355 ****************************************************************************/
357 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
359 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
361 if (!Printer) {
362 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
363 return WERR_BADFID;
367 * It turns out that Windows allows delete printer on a handle
368 * opened by an admin user, then used on a pipe handle created
369 * by an anonymous user..... but they're working on security.... riiight !
370 * JRA.
373 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
374 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
375 return WERR_ACCESS_DENIED;
378 /* this does not need a become root since the access check has been
379 done on the handle already */
381 if (del_a_printer( Printer->sharename ) != 0) {
382 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
383 return WERR_BADFID;
386 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
387 Printer->sharename );
390 /****************************************************************************
391 Return the snum of a printer corresponding to an handle.
392 ****************************************************************************/
394 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
395 struct share_params **params)
397 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
399 if (!Printer) {
400 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
401 return False;
404 switch (Printer->printer_type) {
405 case SPLHND_PRINTER:
406 DEBUG(4,("short name:%s\n", Printer->sharename));
407 *number = print_queue_snum(Printer->sharename);
408 return (*number != -1);
409 case SPLHND_SERVER:
410 return False;
411 default:
412 return False;
416 /****************************************************************************
417 Set printer handle type.
418 Check if it's \\server or \\server\printer
419 ****************************************************************************/
421 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
423 DEBUG(3,("Setting printer type=%s\n", handlename));
425 if ( strlen(handlename) < 3 ) {
426 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
427 return False;
430 /* it's a print server */
431 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
432 DEBUGADD(4,("Printer is a print server\n"));
433 Printer->printer_type = SPLHND_SERVER;
435 /* it's a printer (set_printer_hnd_name() will handle port monitors */
436 else {
437 DEBUGADD(4,("Printer is a printer\n"));
438 Printer->printer_type = SPLHND_PRINTER;
441 return True;
444 /****************************************************************************
445 Set printer handle name.. Accept names like \\server, \\server\printer,
446 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
447 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
448 XcvDataPort() interface.
449 ****************************************************************************/
451 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
453 int snum;
454 int n_services=lp_numservices();
455 char *aprinter, *printername;
456 const char *servername;
457 fstring sname;
458 bool found=False;
459 NT_PRINTER_INFO_LEVEL *printer = NULL;
460 WERROR result;
462 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
464 aprinter = handlename;
465 if ( *handlename == '\\' ) {
466 servername = canon_servername(handlename);
467 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
468 *aprinter = '\0';
469 aprinter++;
471 } else {
472 servername = "";
475 /* save the servername to fill in replies on this handle */
477 if ( !is_myname_or_ipaddr( servername ) )
478 return False;
480 fstrcpy( Printer->servername, servername );
482 if ( Printer->printer_type == SPLHND_SERVER )
483 return True;
485 if ( Printer->printer_type != SPLHND_PRINTER )
486 return False;
488 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
490 /* check for the Port Monitor Interface */
492 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
493 Printer->printer_type = SPLHND_PORTMON_TCP;
494 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
495 found = True;
497 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
498 Printer->printer_type = SPLHND_PORTMON_LOCAL;
499 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
500 found = True;
503 /* Search all sharenames first as this is easier than pulling
504 the printer_info_2 off of disk. Don't use find_service() since
505 that calls out to map_username() */
507 /* do another loop to look for printernames */
509 for (snum=0; !found && snum<n_services; snum++) {
511 /* no point going on if this is not a printer */
513 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
514 continue;
516 fstrcpy(sname, lp_servicename(snum));
517 if ( strequal( aprinter, sname ) ) {
518 found = True;
519 break;
522 /* no point looking up the printer object if
523 we aren't allowing printername != sharename */
525 if ( lp_force_printername(snum) )
526 continue;
528 fstrcpy(sname, lp_servicename(snum));
530 printer = NULL;
532 /* This call doesn't fill in the location or comment from
533 * a CUPS server for efficiency with large numbers of printers.
534 * JRA.
537 result = get_a_printer_search( NULL, &printer, 2, sname );
538 if ( !W_ERROR_IS_OK(result) ) {
539 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
540 sname, win_errstr(result)));
541 continue;
544 /* printername is always returned as \\server\printername */
545 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
546 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
547 printer->info_2->printername));
548 free_a_printer( &printer, 2);
549 continue;
552 printername++;
554 if ( strequal(printername, aprinter) ) {
555 free_a_printer( &printer, 2);
556 found = True;
557 break;
560 DEBUGADD(10, ("printername: %s\n", printername));
562 free_a_printer( &printer, 2);
565 free_a_printer( &printer, 2);
567 if ( !found ) {
568 DEBUGADD(4,("Printer not found\n"));
569 return False;
572 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
574 fstrcpy(Printer->sharename, sname);
576 return True;
579 /****************************************************************************
580 Find first available printer slot. creates a printer handle for you.
581 ****************************************************************************/
583 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
585 Printer_entry *new_printer;
587 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
589 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
590 if (new_printer == NULL) {
591 return false;
593 talloc_set_destructor(new_printer, printer_entry_destructor);
595 if (!create_policy_hnd(p, hnd, new_printer)) {
596 TALLOC_FREE(new_printer);
597 return False;
600 /* Add to the internal list. */
601 DLIST_ADD(printers_list, new_printer);
603 new_printer->notify.option=NULL;
605 if (!set_printer_hnd_printertype(new_printer, name)) {
606 close_printer_handle(p, hnd);
607 return False;
610 if (!set_printer_hnd_name(new_printer, name)) {
611 close_printer_handle(p, hnd);
612 return False;
615 new_printer->access_granted = access_granted;
617 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
619 return True;
622 /***************************************************************************
623 check to see if the client motify handle is monitoring the notification
624 given by (notify_type, notify_field).
625 **************************************************************************/
627 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
628 uint16 notify_field)
630 return True;
633 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
634 uint16 notify_field)
636 SPOOL_NOTIFY_OPTION *option = p->notify.option;
637 uint32 i, j;
640 * Flags should always be zero when the change notify
641 * is registered by the client's spooler. A user Win32 app
642 * might use the flags though instead of the NOTIFY_OPTION_INFO
643 * --jerry
646 if (!option) {
647 return False;
650 if (p->notify.flags)
651 return is_monitoring_event_flags(
652 p->notify.flags, notify_type, notify_field);
654 for (i = 0; i < option->count; i++) {
656 /* Check match for notify_type */
658 if (option->ctr.type[i].type != notify_type)
659 continue;
661 /* Check match for field */
663 for (j = 0; j < option->ctr.type[i].count; j++) {
664 if (option->ctr.type[i].fields[j] == notify_field) {
665 return True;
670 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
671 p->servername, p->sharename, notify_type, notify_field));
673 return False;
676 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
678 static void notify_one_value(struct spoolss_notify_msg *msg,
679 SPOOL_NOTIFY_INFO_DATA *data,
680 TALLOC_CTX *mem_ctx)
682 data->notify_data.value[0] = msg->notify.value[0];
683 data->notify_data.value[1] = 0;
686 static void notify_string(struct spoolss_notify_msg *msg,
687 SPOOL_NOTIFY_INFO_DATA *data,
688 TALLOC_CTX *mem_ctx)
690 UNISTR2 unistr;
692 /* The length of the message includes the trailing \0 */
694 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
696 data->notify_data.data.length = msg->len * 2;
697 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
699 if (!data->notify_data.data.string) {
700 data->notify_data.data.length = 0;
701 return;
704 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
707 static void notify_system_time(struct spoolss_notify_msg *msg,
708 SPOOL_NOTIFY_INFO_DATA *data,
709 TALLOC_CTX *mem_ctx)
711 SYSTEMTIME systime;
712 prs_struct ps;
714 if (msg->len != sizeof(time_t)) {
715 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
716 msg->len));
717 return;
720 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
721 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
722 return;
725 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
726 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
727 prs_mem_free(&ps);
728 return;
731 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
732 prs_mem_free(&ps);
733 return;
736 data->notify_data.data.length = prs_offset(&ps);
737 if (prs_offset(&ps)) {
738 data->notify_data.data.string = (uint16 *)
739 TALLOC(mem_ctx, prs_offset(&ps));
740 if (!data->notify_data.data.string) {
741 prs_mem_free(&ps);
742 return;
744 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
745 } else {
746 data->notify_data.data.string = NULL;
749 prs_mem_free(&ps);
752 struct notify2_message_table {
753 const char *name;
754 void (*fn)(struct spoolss_notify_msg *msg,
755 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
758 static struct notify2_message_table printer_notify_table[] = {
759 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
760 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
761 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
762 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
763 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
764 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
765 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
766 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
767 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
768 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
769 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
770 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
771 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
772 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
773 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
774 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
775 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
776 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
777 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
780 static struct notify2_message_table job_notify_table[] = {
781 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
782 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
783 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
784 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
785 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
786 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
787 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
788 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
789 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
790 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
791 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
792 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
793 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
794 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
795 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
796 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
797 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
798 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
799 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
800 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
801 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
802 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
803 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
804 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
808 /***********************************************************************
809 Allocate talloc context for container object
810 **********************************************************************/
812 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
814 if ( !ctr )
815 return;
817 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
819 return;
822 /***********************************************************************
823 release all allocated memory and zero out structure
824 **********************************************************************/
826 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
828 if ( !ctr )
829 return;
831 if ( ctr->ctx )
832 talloc_destroy(ctr->ctx);
834 ZERO_STRUCTP(ctr);
836 return;
839 /***********************************************************************
840 **********************************************************************/
842 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
844 if ( !ctr )
845 return NULL;
847 return ctr->ctx;
850 /***********************************************************************
851 **********************************************************************/
853 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
855 if ( !ctr || !ctr->msg_groups )
856 return NULL;
858 if ( idx >= ctr->num_groups )
859 return NULL;
861 return &ctr->msg_groups[idx];
865 /***********************************************************************
866 How many groups of change messages do we have ?
867 **********************************************************************/
869 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
871 if ( !ctr )
872 return 0;
874 return ctr->num_groups;
877 /***********************************************************************
878 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
879 **********************************************************************/
881 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
883 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
884 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
885 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
886 int i, new_slot;
888 if ( !ctr || !msg )
889 return 0;
891 /* loop over all groups looking for a matching printer name */
893 for ( i=0; i<ctr->num_groups; i++ ) {
894 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
895 break;
898 /* add a new group? */
900 if ( i == ctr->num_groups ) {
901 ctr->num_groups++;
903 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
904 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
905 return 0;
907 ctr->msg_groups = groups;
909 /* clear the new entry and set the printer name */
911 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
912 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
915 /* add the change messages; 'i' is the correct index now regardless */
917 msg_grp = &ctr->msg_groups[i];
919 msg_grp->num_msgs++;
921 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
922 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
923 return 0;
925 msg_grp->msgs = msg_list;
927 new_slot = msg_grp->num_msgs-1;
928 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
930 /* need to allocate own copy of data */
932 if ( msg->len != 0 )
933 msg_grp->msgs[new_slot].notify.data = (char *)
934 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
936 return ctr->num_groups;
939 /***********************************************************************
940 Send a change notication message on all handles which have a call
941 back registered
942 **********************************************************************/
944 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
946 Printer_entry *p;
947 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
948 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
949 SPOOLSS_NOTIFY_MSG *messages;
950 int sending_msg_count;
952 if ( !msg_group ) {
953 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
954 return;
957 messages = msg_group->msgs;
959 if ( !messages ) {
960 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
961 return;
964 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
966 /* loop over all printers */
968 for (p = printers_list; p; p = p->next) {
969 SPOOL_NOTIFY_INFO_DATA *data;
970 uint32 data_len = 0;
971 uint32 id;
972 int i;
974 /* Is there notification on this handle? */
976 if ( !p->notify.client_connected )
977 continue;
979 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
981 /* For this printer? Print servers always receive
982 notifications. */
984 if ( ( p->printer_type == SPLHND_PRINTER ) &&
985 ( !strequal(msg_group->printername, p->sharename) ) )
986 continue;
988 DEBUG(10,("Our printer\n"));
990 /* allocate the max entries possible */
992 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
993 if (!data) {
994 return;
997 ZERO_STRUCTP(data);
999 /* build the array of change notifications */
1001 sending_msg_count = 0;
1003 for ( i=0; i<msg_group->num_msgs; i++ ) {
1004 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1006 /* Are we monitoring this event? */
1008 if (!is_monitoring_event(p, msg->type, msg->field))
1009 continue;
1011 sending_msg_count++;
1014 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1015 msg->type, msg->field, p->sharename));
1018 * if the is a printer notification handle and not a job notification
1019 * type, then set the id to 0. Other wise just use what was specified
1020 * in the message.
1022 * When registering change notification on a print server handle
1023 * we always need to send back the id (snum) matching the printer
1024 * for which the change took place. For change notify registered
1025 * on a printer handle, this does not matter and the id should be 0.
1027 * --jerry
1030 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1031 id = 0;
1032 else
1033 id = msg->id;
1036 /* Convert unix jobid to smb jobid */
1038 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1039 id = sysjob_to_jobid(msg->id);
1041 if (id == -1) {
1042 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1043 goto done;
1047 construct_info_data( &data[data_len], msg->type, msg->field, id );
1049 switch(msg->type) {
1050 case PRINTER_NOTIFY_TYPE:
1051 if ( printer_notify_table[msg->field].fn )
1052 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1053 break;
1055 case JOB_NOTIFY_TYPE:
1056 if ( job_notify_table[msg->field].fn )
1057 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1058 break;
1060 default:
1061 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1062 goto done;
1065 data_len++;
1068 if ( sending_msg_count ) {
1069 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1070 data_len, data, p->notify.change, 0 );
1074 done:
1075 DEBUG(8,("send_notify2_changes: Exit...\n"));
1076 return;
1079 /***********************************************************************
1080 **********************************************************************/
1082 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1085 uint32 tv_sec, tv_usec;
1086 size_t offset = 0;
1088 /* Unpack message */
1090 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1091 msg->printer);
1093 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1094 &tv_sec, &tv_usec,
1095 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1097 if (msg->len == 0)
1098 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1099 &msg->notify.value[0], &msg->notify.value[1]);
1100 else
1101 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1102 &msg->len, &msg->notify.data);
1104 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1105 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1107 tv->tv_sec = tv_sec;
1108 tv->tv_usec = tv_usec;
1110 if (msg->len == 0)
1111 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1112 msg->notify.value[1]));
1113 else
1114 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1116 return True;
1119 /********************************************************************
1120 Receive a notify2 message list
1121 ********************************************************************/
1123 static void receive_notify2_message_list(struct messaging_context *msg,
1124 void *private_data,
1125 uint32_t msg_type,
1126 struct server_id server_id,
1127 DATA_BLOB *data)
1129 size_t msg_count, i;
1130 char *buf = (char *)data->data;
1131 char *msg_ptr;
1132 size_t msg_len;
1133 SPOOLSS_NOTIFY_MSG notify;
1134 SPOOLSS_NOTIFY_MSG_CTR messages;
1135 int num_groups;
1137 if (data->length < 4) {
1138 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1139 return;
1142 msg_count = IVAL(buf, 0);
1143 msg_ptr = buf + 4;
1145 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1147 if (msg_count == 0) {
1148 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1149 return;
1152 /* initialize the container */
1154 ZERO_STRUCT( messages );
1155 notify_msg_ctr_init( &messages );
1158 * build message groups for each printer identified
1159 * in a change_notify msg. Remember that a PCN message
1160 * includes the handle returned for the srv_spoolss_replyopenprinter()
1161 * call. Therefore messages are grouped according to printer handle.
1164 for ( i=0; i<msg_count; i++ ) {
1165 struct timeval msg_tv;
1167 if (msg_ptr + 4 - buf > data->length) {
1168 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1169 return;
1172 msg_len = IVAL(msg_ptr,0);
1173 msg_ptr += 4;
1175 if (msg_ptr + msg_len - buf > data->length) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1177 return;
1180 /* unpack messages */
1182 ZERO_STRUCT( notify );
1183 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1184 msg_ptr += msg_len;
1186 /* add to correct list in container */
1188 notify_msg_ctr_addmsg( &messages, &notify );
1190 /* free memory that might have been allocated by notify2_unpack_msg() */
1192 if ( notify.len != 0 )
1193 SAFE_FREE( notify.notify.data );
1196 /* process each group of messages */
1198 num_groups = notify_msg_ctr_numgroups( &messages );
1199 for ( i=0; i<num_groups; i++ )
1200 send_notify2_changes( &messages, i );
1203 /* cleanup */
1205 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1207 notify_msg_ctr_destroy( &messages );
1209 return;
1212 /********************************************************************
1213 Send a message to ourself about new driver being installed
1214 so we can upgrade the information for each printer bound to this
1215 driver
1216 ********************************************************************/
1218 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1220 int len = strlen(drivername);
1222 if (!len)
1223 return False;
1225 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1226 drivername));
1228 messaging_send_buf(smbd_messaging_context(), procid_self(),
1229 MSG_PRINTER_DRVUPGRADE,
1230 (uint8 *)drivername, len+1);
1232 return True;
1235 /**********************************************************************
1236 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1237 over all printers, upgrading ones as necessary
1238 **********************************************************************/
1240 void do_drv_upgrade_printer(struct messaging_context *msg,
1241 void *private_data,
1242 uint32_t msg_type,
1243 struct server_id server_id,
1244 DATA_BLOB *data)
1246 fstring drivername;
1247 int snum;
1248 int n_services = lp_numservices();
1249 size_t len;
1251 len = MIN(data->length,sizeof(drivername)-1);
1252 strncpy(drivername, (const char *)data->data, len);
1254 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1256 /* Iterate the printer list */
1258 for (snum=0; snum<n_services; snum++)
1260 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1262 WERROR result;
1263 NT_PRINTER_INFO_LEVEL *printer = NULL;
1265 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1266 if (!W_ERROR_IS_OK(result))
1267 continue;
1269 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1271 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1273 /* all we care about currently is the change_id */
1275 result = mod_a_printer(printer, 2);
1276 if (!W_ERROR_IS_OK(result)) {
1277 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1278 win_errstr(result)));
1282 free_a_printer(&printer, 2);
1286 /* all done */
1289 /********************************************************************
1290 Update the cache for all printq's with a registered client
1291 connection
1292 ********************************************************************/
1294 void update_monitored_printq_cache( void )
1296 Printer_entry *printer = printers_list;
1297 int snum;
1299 /* loop through all printers and update the cache where
1300 client_connected == True */
1301 while ( printer )
1303 if ( (printer->printer_type == SPLHND_PRINTER)
1304 && printer->notify.client_connected )
1306 snum = print_queue_snum(printer->sharename);
1307 print_queue_status( snum, NULL, NULL );
1310 printer = printer->next;
1313 return;
1315 /********************************************************************
1316 Send a message to ourself about new driver being installed
1317 so we can upgrade the information for each printer bound to this
1318 driver
1319 ********************************************************************/
1321 static bool srv_spoolss_reset_printerdata(char* drivername)
1323 int len = strlen(drivername);
1325 if (!len)
1326 return False;
1328 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1329 drivername));
1331 messaging_send_buf(smbd_messaging_context(), procid_self(),
1332 MSG_PRINTERDATA_INIT_RESET,
1333 (uint8 *)drivername, len+1);
1335 return True;
1338 /**********************************************************************
1339 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1340 over all printers, resetting printer data as neessary
1341 **********************************************************************/
1343 void reset_all_printerdata(struct messaging_context *msg,
1344 void *private_data,
1345 uint32_t msg_type,
1346 struct server_id server_id,
1347 DATA_BLOB *data)
1349 fstring drivername;
1350 int snum;
1351 int n_services = lp_numservices();
1352 size_t len;
1354 len = MIN( data->length, sizeof(drivername)-1 );
1355 strncpy( drivername, (const char *)data->data, len );
1357 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1359 /* Iterate the printer list */
1361 for ( snum=0; snum<n_services; snum++ )
1363 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1365 WERROR result;
1366 NT_PRINTER_INFO_LEVEL *printer = NULL;
1368 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1369 if ( !W_ERROR_IS_OK(result) )
1370 continue;
1373 * if the printer is bound to the driver,
1374 * then reset to the new driver initdata
1377 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1379 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1381 if ( !set_driver_init(printer, 2) ) {
1382 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1383 printer->info_2->printername, printer->info_2->drivername));
1386 result = mod_a_printer( printer, 2 );
1387 if ( !W_ERROR_IS_OK(result) ) {
1388 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1389 get_dos_error_msg(result)));
1393 free_a_printer( &printer, 2 );
1397 /* all done */
1399 return;
1402 /****************************************************************
1403 _spoolss_OpenPrinter
1404 ****************************************************************/
1406 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1407 struct spoolss_OpenPrinter *r)
1409 struct spoolss_OpenPrinterEx e;
1410 WERROR werr;
1412 ZERO_STRUCT(e.in.userlevel);
1414 e.in.printername = r->in.printername;
1415 e.in.datatype = r->in.datatype;
1416 e.in.devmode_ctr = r->in.devmode_ctr;
1417 e.in.access_mask = r->in.access_mask;
1418 e.in.level = 0;
1420 e.out.handle = r->out.handle;
1422 werr = _spoolss_OpenPrinterEx(p, &e);
1424 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1425 /* OpenPrinterEx returns this for a bad
1426 * printer name. We must return WERR_INVALID_PRINTER_NAME
1427 * instead.
1429 werr = WERR_INVALID_PRINTER_NAME;
1432 return werr;
1435 /********************************************************************
1436 FIXME: temporary convert_devicemode_new function
1437 ********************************************************************/
1439 static bool convert_devicemode_new(const char *printername,
1440 struct spoolss_DeviceMode *devmode,
1441 NT_DEVICEMODE **pp_nt_devmode)
1443 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1446 * Ensure nt_devmode is a valid pointer
1447 * as we will be overwriting it.
1450 if (nt_devmode == NULL) {
1451 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1452 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1453 return false;
1456 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1457 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1459 nt_devmode->specversion = devmode->specversion;
1460 nt_devmode->driverversion = devmode->driverversion;
1461 nt_devmode->size = devmode->size;
1462 nt_devmode->fields = devmode->fields;
1463 nt_devmode->orientation = devmode->orientation;
1464 nt_devmode->papersize = devmode->papersize;
1465 nt_devmode->paperlength = devmode->paperlength;
1466 nt_devmode->paperwidth = devmode->paperwidth;
1467 nt_devmode->scale = devmode->scale;
1468 nt_devmode->copies = devmode->copies;
1469 nt_devmode->defaultsource = devmode->defaultsource;
1470 nt_devmode->printquality = devmode->printquality;
1471 nt_devmode->color = devmode->color;
1472 nt_devmode->duplex = devmode->duplex;
1473 nt_devmode->yresolution = devmode->yresolution;
1474 nt_devmode->ttoption = devmode->ttoption;
1475 nt_devmode->collate = devmode->collate;
1477 nt_devmode->logpixels = devmode->logpixels;
1478 nt_devmode->bitsperpel = devmode->bitsperpel;
1479 nt_devmode->pelswidth = devmode->pelswidth;
1480 nt_devmode->pelsheight = devmode->pelsheight;
1481 nt_devmode->displayflags = devmode->displayflags;
1482 nt_devmode->displayfrequency = devmode->displayfrequency;
1483 nt_devmode->icmmethod = devmode->icmmethod;
1484 nt_devmode->icmintent = devmode->icmintent;
1485 nt_devmode->mediatype = devmode->mediatype;
1486 nt_devmode->dithertype = devmode->dithertype;
1487 nt_devmode->reserved1 = devmode->reserved1;
1488 nt_devmode->reserved2 = devmode->reserved2;
1489 nt_devmode->panningwidth = devmode->panningwidth;
1490 nt_devmode->panningheight = devmode->panningheight;
1493 * Only change private and driverextra if the incoming devmode
1494 * has a new one. JRA.
1497 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1498 SAFE_FREE(nt_devmode->nt_dev_private);
1499 nt_devmode->driverextra = devmode->__driverextra_length;
1500 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1501 return false;
1502 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1505 *pp_nt_devmode = nt_devmode;
1507 return true;
1510 /****************************************************************
1511 _spoolss_OpenPrinterEx
1512 ****************************************************************/
1514 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1515 struct spoolss_OpenPrinterEx *r)
1517 POLICY_HND *handle = r->out.handle;
1518 char *name = CONST_DISCARD(char *, r->in.printername);
1519 int snum;
1520 Printer_entry *Printer=NULL;
1522 if (!name) {
1523 return WERR_INVALID_PARAM;
1526 /* some sanity check because you can open a printer or a print server */
1527 /* aka: \\server\printer or \\server */
1529 DEBUGADD(3,("checking name: %s\n",name));
1531 if (!open_printer_hnd(p, handle, name, 0)) {
1532 return WERR_INVALID_PARAM;
1535 Printer=find_printer_index_by_hnd(p, handle);
1536 if ( !Printer ) {
1537 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1538 "handle we created for printer %s\n", name ));
1539 close_printer_handle(p,handle);
1540 return WERR_INVALID_PARAM;
1544 * First case: the user is opening the print server:
1546 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1547 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1549 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1550 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1551 * or if the user is listed in the smb.conf printer admin parameter.
1553 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1554 * client view printer folder, but does not show the MSAPW.
1556 * Note: this test needs code to check access rights here too. Jeremy
1557 * could you look at this?
1559 * Second case: the user is opening a printer:
1560 * NT doesn't let us connect to a printer if the connecting user
1561 * doesn't have print permission.
1563 * Third case: user is opening a Port Monitor
1564 * access checks same as opening a handle to the print server.
1567 switch (Printer->printer_type )
1569 case SPLHND_SERVER:
1570 case SPLHND_PORTMON_TCP:
1571 case SPLHND_PORTMON_LOCAL:
1572 /* Printserver handles use global struct... */
1574 snum = -1;
1576 /* Map standard access rights to object specific access rights */
1578 se_map_standard(&r->in.access_mask,
1579 &printserver_std_mapping);
1581 /* Deny any object specific bits that don't apply to print
1582 servers (i.e printer and job specific bits) */
1584 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1586 if (r->in.access_mask &
1587 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1588 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1589 close_printer_handle(p, handle);
1590 return WERR_ACCESS_DENIED;
1593 /* Allow admin access */
1595 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1597 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1599 if (!lp_ms_add_printer_wizard()) {
1600 close_printer_handle(p, handle);
1601 return WERR_ACCESS_DENIED;
1604 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1605 and not a printer admin, then fail */
1607 if ((p->server_info->utok.uid != 0) &&
1608 !user_has_privileges(p->server_info->ptok,
1609 &se_printop ) &&
1610 !token_contains_name_in_list(
1611 uidtoname(p->server_info->utok.uid),
1612 NULL, NULL,
1613 p->server_info->ptok,
1614 lp_printer_admin(snum))) {
1615 close_printer_handle(p, handle);
1616 return WERR_ACCESS_DENIED;
1619 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1621 else
1623 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1626 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1627 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1629 /* We fall through to return WERR_OK */
1630 break;
1632 case SPLHND_PRINTER:
1633 /* NT doesn't let us connect to a printer if the connecting user
1634 doesn't have print permission. */
1636 if (!get_printer_snum(p, handle, &snum, NULL)) {
1637 close_printer_handle(p, handle);
1638 return WERR_BADFID;
1641 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1643 /* map an empty access mask to the minimum access mask */
1644 if (r->in.access_mask == 0x0)
1645 r->in.access_mask = PRINTER_ACCESS_USE;
1648 * If we are not serving the printer driver for this printer,
1649 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1650 * will keep NT clients happy --jerry
1653 if (lp_use_client_driver(snum)
1654 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1656 r->in.access_mask = PRINTER_ACCESS_USE;
1659 /* check smb.conf parameters and the the sec_desc */
1661 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1662 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1663 return WERR_ACCESS_DENIED;
1666 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1667 p->server_info->ptok, snum) ||
1668 !print_access_check(p->server_info, snum,
1669 r->in.access_mask)) {
1670 DEBUG(3, ("access DENIED for printer open\n"));
1671 close_printer_handle(p, handle);
1672 return WERR_ACCESS_DENIED;
1675 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1676 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1677 close_printer_handle(p, handle);
1678 return WERR_ACCESS_DENIED;
1681 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1682 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1683 else
1684 r->in.access_mask = PRINTER_ACCESS_USE;
1686 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1687 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1689 break;
1691 default:
1692 /* sanity check to prevent programmer error */
1693 return WERR_BADFID;
1696 Printer->access_granted = r->in.access_mask;
1699 * If the client sent a devmode in the OpenPrinter() call, then
1700 * save it here in case we get a job submission on this handle
1703 if ( (Printer->printer_type != SPLHND_SERVER)
1704 && r->in.devmode_ctr.devmode )
1706 convert_devicemode_new(Printer->sharename,
1707 r->in.devmode_ctr.devmode,
1708 &Printer->nt_devmode);
1711 #if 0 /* JERRY -- I'm doubtful this is really effective */
1712 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713 optimization in Windows 2000 clients --jerry */
1715 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1716 && (RA_WIN2K == get_remote_arch()) )
1718 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1719 sys_usleep( 500000 );
1721 #endif
1723 return WERR_OK;
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1730 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1732 bool ret;
1734 switch (level) {
1735 case 2:
1736 /* allocate memory if needed. Messy because
1737 convert_printer_info is used to update an existing
1738 printer or build a new one */
1740 if ( !printer->info_2 ) {
1741 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1742 if ( !printer->info_2 ) {
1743 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1744 return False;
1748 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1749 printer->info_2->setuptime = time(NULL);
1751 return ret;
1754 return False;
1757 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1758 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1760 bool result = True;
1762 switch (level) {
1763 case 3:
1764 printer->info_3=NULL;
1765 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1766 result = False;
1767 break;
1768 case 6:
1769 printer->info_6=NULL;
1770 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1771 result = False;
1772 break;
1773 default:
1774 break;
1777 return result;
1780 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1781 NT_DEVICEMODE **pp_nt_devmode)
1783 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1786 * Ensure nt_devmode is a valid pointer
1787 * as we will be overwriting it.
1790 if (nt_devmode == NULL) {
1791 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1792 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1793 return False;
1796 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1797 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1799 nt_devmode->specversion=devmode->specversion;
1800 nt_devmode->driverversion=devmode->driverversion;
1801 nt_devmode->size=devmode->size;
1802 nt_devmode->fields=devmode->fields;
1803 nt_devmode->orientation=devmode->orientation;
1804 nt_devmode->papersize=devmode->papersize;
1805 nt_devmode->paperlength=devmode->paperlength;
1806 nt_devmode->paperwidth=devmode->paperwidth;
1807 nt_devmode->scale=devmode->scale;
1808 nt_devmode->copies=devmode->copies;
1809 nt_devmode->defaultsource=devmode->defaultsource;
1810 nt_devmode->printquality=devmode->printquality;
1811 nt_devmode->color=devmode->color;
1812 nt_devmode->duplex=devmode->duplex;
1813 nt_devmode->yresolution=devmode->yresolution;
1814 nt_devmode->ttoption=devmode->ttoption;
1815 nt_devmode->collate=devmode->collate;
1817 nt_devmode->logpixels=devmode->logpixels;
1818 nt_devmode->bitsperpel=devmode->bitsperpel;
1819 nt_devmode->pelswidth=devmode->pelswidth;
1820 nt_devmode->pelsheight=devmode->pelsheight;
1821 nt_devmode->displayflags=devmode->displayflags;
1822 nt_devmode->displayfrequency=devmode->displayfrequency;
1823 nt_devmode->icmmethod=devmode->icmmethod;
1824 nt_devmode->icmintent=devmode->icmintent;
1825 nt_devmode->mediatype=devmode->mediatype;
1826 nt_devmode->dithertype=devmode->dithertype;
1827 nt_devmode->reserved1=devmode->reserved1;
1828 nt_devmode->reserved2=devmode->reserved2;
1829 nt_devmode->panningwidth=devmode->panningwidth;
1830 nt_devmode->panningheight=devmode->panningheight;
1833 * Only change private and driverextra if the incoming devmode
1834 * has a new one. JRA.
1837 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1838 SAFE_FREE(nt_devmode->nt_dev_private);
1839 nt_devmode->driverextra=devmode->driverextra;
1840 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1841 return False;
1842 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1845 *pp_nt_devmode = nt_devmode;
1847 return True;
1850 /********************************************************************
1851 * _spoolss_enddocprinter_internal.
1852 ********************************************************************/
1854 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1856 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1857 int snum;
1859 if (!Printer) {
1860 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1861 return WERR_BADFID;
1864 if (!get_printer_snum(p, handle, &snum, NULL))
1865 return WERR_BADFID;
1867 Printer->document_started=False;
1868 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1869 /* error codes unhandled so far ... */
1871 return WERR_OK;
1874 /****************************************************************
1875 _spoolss_ClosePrinter
1876 ****************************************************************/
1878 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1879 struct spoolss_ClosePrinter *r)
1881 POLICY_HND *handle = r->in.handle;
1883 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1885 if (Printer && Printer->document_started)
1886 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1888 if (!close_printer_handle(p, handle))
1889 return WERR_BADFID;
1891 /* clear the returned printer handle. Observed behavior
1892 from Win2k server. Don't think this really matters.
1893 Previous code just copied the value of the closed
1894 handle. --jerry */
1896 ZERO_STRUCTP(r->out.handle);
1898 return WERR_OK;
1901 /****************************************************************
1902 _spoolss_DeletePrinter
1903 ****************************************************************/
1905 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1906 struct spoolss_DeletePrinter *r)
1908 POLICY_HND *handle = r->in.handle;
1909 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1910 WERROR result;
1912 if (Printer && Printer->document_started)
1913 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1915 result = delete_printer_handle(p, handle);
1917 update_c_setprinter(False);
1919 return result;
1922 /*******************************************************************
1923 * static function to lookup the version id corresponding to an
1924 * long architecture string
1925 ******************************************************************/
1927 static int get_version_id (char * arch)
1929 int i;
1930 struct table_node archi_table[]= {
1932 {"Windows 4.0", "WIN40", 0 },
1933 {"Windows NT x86", "W32X86", 2 },
1934 {"Windows NT R4000", "W32MIPS", 2 },
1935 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1936 {"Windows NT PowerPC", "W32PPC", 2 },
1937 {"Windows IA64", "IA64", 3 },
1938 {"Windows x64", "x64", 3 },
1939 {NULL, "", -1 }
1942 for (i=0; archi_table[i].long_archi != NULL; i++)
1944 if (strcmp(arch, archi_table[i].long_archi) == 0)
1945 return (archi_table[i].version);
1948 return -1;
1951 /****************************************************************
1952 _spoolss_DeletePrinterDriver
1953 ****************************************************************/
1955 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1956 struct spoolss_DeletePrinterDriver *r)
1958 char *driver;
1959 char *arch;
1960 NT_PRINTER_DRIVER_INFO_LEVEL info;
1961 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1962 int version;
1963 WERROR status;
1964 WERROR status_win2k = WERR_ACCESS_DENIED;
1965 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1967 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1968 and not a printer admin, then fail */
1970 if ( (p->server_info->utok.uid != 0)
1971 && !user_has_privileges(p->server_info->ptok, &se_printop )
1972 && !token_contains_name_in_list(
1973 uidtoname(p->server_info->utok.uid), NULL,
1974 NULL, p->server_info->ptok,
1975 lp_printer_admin(-1)) )
1977 return WERR_ACCESS_DENIED;
1980 driver = CONST_DISCARD(char *, r->in.driver);
1981 arch = CONST_DISCARD(char *, r->in.architecture);
1983 /* check that we have a valid driver name first */
1985 if ((version=get_version_id(arch)) == -1)
1986 return WERR_INVALID_ENVIRONMENT;
1988 ZERO_STRUCT(info);
1989 ZERO_STRUCT(info_win2k);
1991 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1993 /* try for Win2k driver if "Windows NT x86" */
1995 if ( version == 2 ) {
1996 version = 3;
1997 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1998 status = WERR_UNKNOWN_PRINTER_DRIVER;
1999 goto done;
2002 /* otherwise it was a failure */
2003 else {
2004 status = WERR_UNKNOWN_PRINTER_DRIVER;
2005 goto done;
2010 if (printer_driver_in_use(info.info_3)) {
2011 status = WERR_PRINTER_DRIVER_IN_USE;
2012 goto done;
2015 if ( version == 2 )
2017 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2019 /* if we get to here, we now have 2 driver info structures to remove */
2020 /* remove the Win2k driver first*/
2022 status_win2k = delete_printer_driver(
2023 p, info_win2k.info_3, 3, False );
2024 free_a_printer_driver( info_win2k, 3 );
2026 /* this should not have failed---if it did, report to client */
2027 if ( !W_ERROR_IS_OK(status_win2k) )
2029 status = status_win2k;
2030 goto done;
2035 status = delete_printer_driver(p, info.info_3, version, False);
2037 /* if at least one of the deletes succeeded return OK */
2039 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2040 status = WERR_OK;
2042 done:
2043 free_a_printer_driver( info, 3 );
2045 return status;
2048 /****************************************************************
2049 _spoolss_DeletePrinterDriverEx
2050 ****************************************************************/
2052 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2053 struct spoolss_DeletePrinterDriverEx *r)
2055 char *driver;
2056 char *arch;
2057 NT_PRINTER_DRIVER_INFO_LEVEL info;
2058 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2059 int version;
2060 uint32_t flags = r->in.delete_flags;
2061 bool delete_files;
2062 WERROR status;
2063 WERROR status_win2k = WERR_ACCESS_DENIED;
2064 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2066 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2067 and not a printer admin, then fail */
2069 if ( (p->server_info->utok.uid != 0)
2070 && !user_has_privileges(p->server_info->ptok, &se_printop )
2071 && !token_contains_name_in_list(
2072 uidtoname(p->server_info->utok.uid), NULL, NULL,
2073 p->server_info->ptok, lp_printer_admin(-1)) )
2075 return WERR_ACCESS_DENIED;
2078 driver = CONST_DISCARD(char *, r->in.driver);
2079 arch = CONST_DISCARD(char *, r->in.architecture);
2081 /* check that we have a valid driver name first */
2082 if ((version=get_version_id(arch)) == -1) {
2083 /* this is what NT returns */
2084 return WERR_INVALID_ENVIRONMENT;
2087 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2088 version = r->in.version;
2090 ZERO_STRUCT(info);
2091 ZERO_STRUCT(info_win2k);
2093 status = get_a_printer_driver(&info, 3, driver, arch, version);
2095 if ( !W_ERROR_IS_OK(status) )
2098 * if the client asked for a specific version,
2099 * or this is something other than Windows NT x86,
2100 * then we've failed
2103 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2104 goto done;
2106 /* try for Win2k driver if "Windows NT x86" */
2108 version = 3;
2109 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2110 status = WERR_UNKNOWN_PRINTER_DRIVER;
2111 goto done;
2115 if ( printer_driver_in_use(info.info_3) ) {
2116 status = WERR_PRINTER_DRIVER_IN_USE;
2117 goto done;
2121 * we have a couple of cases to consider.
2122 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2123 * then the delete should fail if **any** files overlap with
2124 * other drivers
2125 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2126 * non-overlapping files
2127 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2128 * is set, the do not delete any files
2129 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2132 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2134 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2136 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2137 /* no idea of the correct error here */
2138 status = WERR_ACCESS_DENIED;
2139 goto done;
2143 /* also check for W32X86/3 if necessary; maybe we already have? */
2145 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2146 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2149 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2150 /* no idea of the correct error here */
2151 free_a_printer_driver( info_win2k, 3 );
2152 status = WERR_ACCESS_DENIED;
2153 goto done;
2156 /* if we get to here, we now have 2 driver info structures to remove */
2157 /* remove the Win2k driver first*/
2159 status_win2k = delete_printer_driver(
2160 p, info_win2k.info_3, 3, delete_files);
2161 free_a_printer_driver( info_win2k, 3 );
2163 /* this should not have failed---if it did, report to client */
2165 if ( !W_ERROR_IS_OK(status_win2k) )
2166 goto done;
2170 status = delete_printer_driver(p, info.info_3, version, delete_files);
2172 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2173 status = WERR_OK;
2174 done:
2175 free_a_printer_driver( info, 3 );
2177 return status;
2181 /****************************************************************************
2182 Internal routine for retreiving printerdata
2183 ***************************************************************************/
2185 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2186 const char *key, const char *value, uint32 *type, uint8 **data,
2187 uint32 *needed, uint32 in_size )
2189 REGISTRY_VALUE *val;
2190 uint32 size;
2191 int data_len;
2193 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2194 return WERR_BADFILE;
2196 *type = regval_type( val );
2198 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2200 size = regval_size( val );
2202 /* copy the min(in_size, len) */
2204 if ( in_size ) {
2205 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2207 /* special case for 0 length values */
2208 if ( data_len ) {
2209 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2210 return WERR_NOMEM;
2212 else {
2213 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2214 return WERR_NOMEM;
2217 else
2218 *data = NULL;
2220 *needed = size;
2222 DEBUG(5,("get_printer_dataex: copy done\n"));
2224 return WERR_OK;
2227 /****************************************************************************
2228 Internal routine for removing printerdata
2229 ***************************************************************************/
2231 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2233 return delete_printer_data( printer->info_2, key, value );
2236 /****************************************************************************
2237 Internal routine for storing printerdata
2238 ***************************************************************************/
2240 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2241 uint32 type, uint8 *data, int real_len )
2243 /* the registry objects enforce uniqueness based on value name */
2245 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2248 /********************************************************************
2249 GetPrinterData on a printer server Handle.
2250 ********************************************************************/
2252 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2254 int i;
2256 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2258 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2259 *type = REG_DWORD;
2260 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2261 return WERR_NOMEM;
2262 SIVAL(*data, 0, 0x00);
2263 *needed = 0x4;
2264 return WERR_OK;
2267 if (!StrCaseCmp(value, "BeepEnabled")) {
2268 *type = REG_DWORD;
2269 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2270 return WERR_NOMEM;
2271 SIVAL(*data, 0, 0x00);
2272 *needed = 0x4;
2273 return WERR_OK;
2276 if (!StrCaseCmp(value, "EventLog")) {
2277 *type = REG_DWORD;
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2279 return WERR_NOMEM;
2280 /* formally was 0x1b */
2281 SIVAL(*data, 0, 0x0);
2282 *needed = 0x4;
2283 return WERR_OK;
2286 if (!StrCaseCmp(value, "NetPopup")) {
2287 *type = REG_DWORD;
2288 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2289 return WERR_NOMEM;
2290 SIVAL(*data, 0, 0x00);
2291 *needed = 0x4;
2292 return WERR_OK;
2295 if (!StrCaseCmp(value, "MajorVersion")) {
2296 *type = REG_DWORD;
2297 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2298 return WERR_NOMEM;
2300 /* Windows NT 4.0 seems to not allow uploading of drivers
2301 to a server that reports 0x3 as the MajorVersion.
2302 need to investigate more how Win2k gets around this .
2303 -- jerry */
2305 if ( RA_WINNT == get_remote_arch() )
2306 SIVAL(*data, 0, 2);
2307 else
2308 SIVAL(*data, 0, 3);
2310 *needed = 0x4;
2311 return WERR_OK;
2314 if (!StrCaseCmp(value, "MinorVersion")) {
2315 *type = REG_DWORD;
2316 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2317 return WERR_NOMEM;
2318 SIVAL(*data, 0, 0);
2319 *needed = 0x4;
2320 return WERR_OK;
2323 /* REG_BINARY
2324 * uint32 size = 0x114
2325 * uint32 major = 5
2326 * uint32 minor = [0|1]
2327 * uint32 build = [2195|2600]
2328 * extra unicode string = e.g. "Service Pack 3"
2330 if (!StrCaseCmp(value, "OSVersion")) {
2331 *type = REG_BINARY;
2332 *needed = 0x114;
2334 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2335 return WERR_NOMEM;
2337 SIVAL(*data, 0, *needed); /* size */
2338 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2339 SIVAL(*data, 8, 0);
2340 SIVAL(*data, 12, 2195); /* build */
2342 /* leave extra string empty */
2344 return WERR_OK;
2348 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2349 const char *string="C:\\PRINTERS";
2350 *type = REG_SZ;
2351 *needed = 2*(strlen(string)+1);
2352 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2353 return WERR_NOMEM;
2354 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2356 /* it's done by hand ready to go on the wire */
2357 for (i=0; i<strlen(string); i++) {
2358 (*data)[2*i]=string[i];
2359 (*data)[2*i+1]='\0';
2361 return WERR_OK;
2364 if (!StrCaseCmp(value, "Architecture")) {
2365 const char *string="Windows NT x86";
2366 *type = REG_SZ;
2367 *needed = 2*(strlen(string)+1);
2368 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2369 return WERR_NOMEM;
2370 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2371 for (i=0; i<strlen(string); i++) {
2372 (*data)[2*i]=string[i];
2373 (*data)[2*i+1]='\0';
2375 return WERR_OK;
2378 if (!StrCaseCmp(value, "DsPresent")) {
2379 *type = REG_DWORD;
2380 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2381 return WERR_NOMEM;
2383 /* only show the publish check box if we are a
2384 memeber of a AD domain */
2386 if ( lp_security() == SEC_ADS )
2387 SIVAL(*data, 0, 0x01);
2388 else
2389 SIVAL(*data, 0, 0x00);
2391 *needed = 0x4;
2392 return WERR_OK;
2395 if (!StrCaseCmp(value, "DNSMachineName")) {
2396 const char *hostname = get_mydnsfullname();
2398 if (!hostname)
2399 return WERR_BADFILE;
2400 *type = REG_SZ;
2401 *needed = 2*(strlen(hostname)+1);
2402 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2403 return WERR_NOMEM;
2404 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2405 for (i=0; i<strlen(hostname); i++) {
2406 (*data)[2*i]=hostname[i];
2407 (*data)[2*i+1]='\0';
2409 return WERR_OK;
2413 return WERR_BADFILE;
2416 /********************************************************************
2417 * spoolss_getprinterdata
2418 ********************************************************************/
2420 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2422 POLICY_HND *handle = &q_u->handle;
2423 UNISTR2 *valuename = &q_u->valuename;
2424 uint32 in_size = q_u->size;
2425 uint32 *type = &r_u->type;
2426 uint32 *out_size = &r_u->size;
2427 uint8 **data = &r_u->data;
2428 uint32 *needed = &r_u->needed;
2429 WERROR status;
2430 fstring value;
2431 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2432 NT_PRINTER_INFO_LEVEL *printer = NULL;
2433 int snum = 0;
2436 * Reminder: when it's a string, the length is in BYTES
2437 * even if UNICODE is negociated.
2439 * JFM, 4/19/1999
2442 *out_size = in_size;
2444 /* in case of problem, return some default values */
2446 *needed = 0;
2447 *type = 0;
2449 DEBUG(4,("_spoolss_getprinterdata\n"));
2451 if ( !Printer ) {
2452 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2453 status = WERR_BADFID;
2454 goto done;
2457 unistr2_to_ascii(value, valuename, sizeof(value));
2459 if ( Printer->printer_type == SPLHND_SERVER )
2460 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2461 else
2463 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2464 status = WERR_BADFID;
2465 goto done;
2468 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2469 if ( !W_ERROR_IS_OK(status) )
2470 goto done;
2472 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2474 if ( strequal(value, "ChangeId") ) {
2475 *type = REG_DWORD;
2476 *needed = sizeof(uint32);
2477 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2478 status = WERR_NOMEM;
2479 goto done;
2481 SIVAL( *data, 0, printer->info_2->changeid );
2482 status = WERR_OK;
2484 else
2485 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2488 if (*needed > *out_size)
2489 status = WERR_MORE_DATA;
2491 done:
2492 if ( !W_ERROR_IS_OK(status) )
2494 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2496 /* reply this param doesn't exist */
2498 if ( *out_size ) {
2499 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2500 if ( printer )
2501 free_a_printer( &printer, 2 );
2502 return WERR_NOMEM;
2504 } else {
2505 *data = NULL;
2509 /* cleanup & exit */
2511 if ( printer )
2512 free_a_printer( &printer, 2 );
2514 return status;
2517 /*********************************************************
2518 Connect to the client machine.
2519 **********************************************************/
2521 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2522 struct sockaddr_storage *client_ss, const char *remote_machine)
2524 NTSTATUS ret;
2525 struct cli_state *the_cli;
2526 struct sockaddr_storage rm_addr;
2528 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2529 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2530 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2531 return False;
2534 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2535 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2536 return False;
2538 } else {
2539 char addr[INET6_ADDRSTRLEN];
2540 rm_addr = *client_ss;
2541 print_sockaddr(addr, sizeof(addr), &rm_addr);
2542 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2543 addr));
2546 /* setup the connection */
2548 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2549 &rm_addr, 0, "IPC$", "IPC",
2550 "", /* username */
2551 "", /* domain */
2552 "", /* password */
2553 0, lp_client_signing(), NULL );
2555 if ( !NT_STATUS_IS_OK( ret ) ) {
2556 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2557 remote_machine ));
2558 return False;
2561 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2562 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2563 cli_shutdown(the_cli);
2564 return False;
2568 * Ok - we have an anonymous connection to the IPC$ share.
2569 * Now start the NT Domain stuff :-).
2572 ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2573 if (!NT_STATUS_IS_OK(ret)) {
2574 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2575 remote_machine, nt_errstr(ret)));
2576 cli_shutdown(the_cli);
2577 return False;
2580 return True;
2583 /***************************************************************************
2584 Connect to the client.
2585 ****************************************************************************/
2587 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2588 uint32 localprinter, uint32 type,
2589 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2591 WERROR result;
2592 NTSTATUS status;
2595 * If it's the first connection, contact the client
2596 * and connect to the IPC$ share anonymously
2598 if (smb_connections==0) {
2599 fstring unix_printer;
2601 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2603 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2604 return False;
2606 messaging_register(smbd_messaging_context(), NULL,
2607 MSG_PRINTER_NOTIFY2,
2608 receive_notify2_message_list);
2609 /* Tell the connections db we're now interested in printer
2610 * notify messages. */
2611 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2615 * Tell the specific printing tdb we want messages for this printer
2616 * by registering our PID.
2619 if (!print_notify_register_pid(snum))
2620 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2622 smb_connections++;
2624 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2625 printer,
2626 localprinter,
2627 type,
2629 NULL,
2630 handle,
2631 &result);
2632 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2633 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2634 win_errstr(result)));
2636 return (W_ERROR_IS_OK(result));
2639 /********************************************************************
2640 * _spoolss_rffpcnex
2641 * ReplyFindFirstPrinterChangeNotifyEx
2643 * before replying OK: status=0 a rpc call is made to the workstation
2644 * asking ReplyOpenPrinter
2646 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2647 * called from api_spoolss_rffpcnex
2648 ********************************************************************/
2650 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2652 POLICY_HND *handle = &q_u->handle;
2653 uint32 flags = q_u->flags;
2654 uint32 options = q_u->options;
2655 UNISTR2 *localmachine = &q_u->localmachine;
2656 uint32 printerlocal = q_u->printerlocal;
2657 int snum = -1;
2658 SPOOL_NOTIFY_OPTION *option = q_u->option;
2659 struct sockaddr_storage client_ss;
2661 /* store the notify value in the printer struct */
2663 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2665 if (!Printer) {
2666 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2667 return WERR_BADFID;
2670 Printer->notify.flags=flags;
2671 Printer->notify.options=options;
2672 Printer->notify.printerlocal=printerlocal;
2674 if (Printer->notify.option)
2675 free_spool_notify_option(&Printer->notify.option);
2677 Printer->notify.option=dup_spool_notify_option(option);
2679 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2680 sizeof(Printer->notify.localmachine));
2682 /* Connect to the client machine and send a ReplyOpenPrinter */
2684 if ( Printer->printer_type == SPLHND_SERVER)
2685 snum = -1;
2686 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2687 !get_printer_snum(p, handle, &snum, NULL) )
2688 return WERR_BADFID;
2690 if (!interpret_string_addr(&client_ss, p->client_address,
2691 AI_NUMERICHOST)) {
2692 return WERR_SERVER_UNAVAILABLE;
2695 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2696 Printer->notify.printerlocal, 1,
2697 &Printer->notify.client_hnd, &client_ss))
2698 return WERR_SERVER_UNAVAILABLE;
2700 Printer->notify.client_connected=True;
2702 return WERR_OK;
2705 /*******************************************************************
2706 * fill a notify_info_data with the servername
2707 ********************************************************************/
2709 void spoolss_notify_server_name(int snum,
2710 SPOOL_NOTIFY_INFO_DATA *data,
2711 print_queue_struct *queue,
2712 NT_PRINTER_INFO_LEVEL *printer,
2713 TALLOC_CTX *mem_ctx)
2715 smb_ucs2_t *temp = NULL;
2716 uint32 len;
2718 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2719 if (len == (uint32)-1) {
2720 len = 0;
2723 data->notify_data.data.length = len;
2724 if (len) {
2725 data->notify_data.data.string = (uint16 *)temp;
2726 } else {
2727 data->notify_data.data.string = NULL;
2731 /*******************************************************************
2732 * fill a notify_info_data with the printername (not including the servername).
2733 ********************************************************************/
2735 void spoolss_notify_printer_name(int snum,
2736 SPOOL_NOTIFY_INFO_DATA *data,
2737 print_queue_struct *queue,
2738 NT_PRINTER_INFO_LEVEL *printer,
2739 TALLOC_CTX *mem_ctx)
2741 smb_ucs2_t *temp = NULL;
2742 uint32 len;
2744 /* the notify name should not contain the \\server\ part */
2745 char *p = strrchr(printer->info_2->printername, '\\');
2747 if (!p) {
2748 p = printer->info_2->printername;
2749 } else {
2750 p++;
2753 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2754 if (len == (uint32)-1) {
2755 len = 0;
2758 data->notify_data.data.length = len;
2759 if (len) {
2760 data->notify_data.data.string = (uint16 *)temp;
2761 } else {
2762 data->notify_data.data.string = NULL;
2766 /*******************************************************************
2767 * fill a notify_info_data with the servicename
2768 ********************************************************************/
2770 void spoolss_notify_share_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2776 smb_ucs2_t *temp = NULL;
2777 uint32 len;
2779 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2780 if (len == (uint32)-1) {
2781 len = 0;
2784 data->notify_data.data.length = len;
2785 if (len) {
2786 data->notify_data.data.string = (uint16 *)temp;
2787 } else {
2788 data->notify_data.data.string = NULL;
2793 /*******************************************************************
2794 * fill a notify_info_data with the port name
2795 ********************************************************************/
2797 void spoolss_notify_port_name(int snum,
2798 SPOOL_NOTIFY_INFO_DATA *data,
2799 print_queue_struct *queue,
2800 NT_PRINTER_INFO_LEVEL *printer,
2801 TALLOC_CTX *mem_ctx)
2803 smb_ucs2_t *temp = NULL;
2804 uint32 len;
2806 /* even if it's strange, that's consistant in all the code */
2808 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2809 if (len == (uint32)-1) {
2810 len = 0;
2813 data->notify_data.data.length = len;
2814 if (len) {
2815 data->notify_data.data.string = (uint16 *)temp;
2816 } else {
2817 data->notify_data.data.string = NULL;
2821 /*******************************************************************
2822 * fill a notify_info_data with the printername
2823 * but it doesn't exist, have to see what to do
2824 ********************************************************************/
2826 void spoolss_notify_driver_name(int snum,
2827 SPOOL_NOTIFY_INFO_DATA *data,
2828 print_queue_struct *queue,
2829 NT_PRINTER_INFO_LEVEL *printer,
2830 TALLOC_CTX *mem_ctx)
2832 smb_ucs2_t *temp = NULL;
2833 uint32 len;
2835 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2836 if (len == (uint32)-1) {
2837 len = 0;
2840 data->notify_data.data.length = len;
2841 if (len) {
2842 data->notify_data.data.string = (uint16 *)temp;
2843 } else {
2844 data->notify_data.data.string = NULL;
2848 /*******************************************************************
2849 * fill a notify_info_data with the comment
2850 ********************************************************************/
2852 void spoolss_notify_comment(int snum,
2853 SPOOL_NOTIFY_INFO_DATA *data,
2854 print_queue_struct *queue,
2855 NT_PRINTER_INFO_LEVEL *printer,
2856 TALLOC_CTX *mem_ctx)
2858 smb_ucs2_t *temp = NULL;
2859 uint32 len;
2861 if (*printer->info_2->comment == '\0')
2862 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2863 else
2864 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2866 if (len == (uint32)-1) {
2867 len = 0;
2869 data->notify_data.data.length = len;
2870 if (len) {
2871 data->notify_data.data.string = (uint16 *)temp;
2872 } else {
2873 data->notify_data.data.string = NULL;
2877 /*******************************************************************
2878 * fill a notify_info_data with the comment
2879 * location = "Room 1, floor 2, building 3"
2880 ********************************************************************/
2882 void spoolss_notify_location(int snum,
2883 SPOOL_NOTIFY_INFO_DATA *data,
2884 print_queue_struct *queue,
2885 NT_PRINTER_INFO_LEVEL *printer,
2886 TALLOC_CTX *mem_ctx)
2888 smb_ucs2_t *temp = NULL;
2889 uint32 len;
2891 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2892 if (len == (uint32)-1) {
2893 len = 0;
2896 data->notify_data.data.length = len;
2897 if (len) {
2898 data->notify_data.data.string = (uint16 *)temp;
2899 } else {
2900 data->notify_data.data.string = NULL;
2904 /*******************************************************************
2905 * fill a notify_info_data with the device mode
2906 * jfm:xxxx don't to it for know but that's a real problem !!!
2907 ********************************************************************/
2909 static void spoolss_notify_devmode(int snum,
2910 SPOOL_NOTIFY_INFO_DATA *data,
2911 print_queue_struct *queue,
2912 NT_PRINTER_INFO_LEVEL *printer,
2913 TALLOC_CTX *mem_ctx)
2915 /* for a dummy implementation we have to zero the fields */
2916 data->notify_data.data.length = 0;
2917 data->notify_data.data.string = NULL;
2920 /*******************************************************************
2921 * fill a notify_info_data with the separator file name
2922 ********************************************************************/
2924 void spoolss_notify_sepfile(int snum,
2925 SPOOL_NOTIFY_INFO_DATA *data,
2926 print_queue_struct *queue,
2927 NT_PRINTER_INFO_LEVEL *printer,
2928 TALLOC_CTX *mem_ctx)
2930 smb_ucs2_t *temp = NULL;
2931 uint32 len;
2933 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2934 if (len == (uint32)-1) {
2935 len = 0;
2938 data->notify_data.data.length = len;
2939 if (len) {
2940 data->notify_data.data.string = (uint16 *)temp;
2941 } else {
2942 data->notify_data.data.string = NULL;
2946 /*******************************************************************
2947 * fill a notify_info_data with the print processor
2948 * jfm:xxxx return always winprint to indicate we don't do anything to it
2949 ********************************************************************/
2951 void spoolss_notify_print_processor(int snum,
2952 SPOOL_NOTIFY_INFO_DATA *data,
2953 print_queue_struct *queue,
2954 NT_PRINTER_INFO_LEVEL *printer,
2955 TALLOC_CTX *mem_ctx)
2957 smb_ucs2_t *temp = NULL;
2958 uint32 len;
2960 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
2961 if (len == (uint32)-1) {
2962 len = 0;
2965 data->notify_data.data.length = len;
2966 if (len) {
2967 data->notify_data.data.string = (uint16 *)temp;
2968 } else {
2969 data->notify_data.data.string = NULL;
2973 /*******************************************************************
2974 * fill a notify_info_data with the print processor options
2975 * jfm:xxxx send an empty string
2976 ********************************************************************/
2978 void spoolss_notify_parameters(int snum,
2979 SPOOL_NOTIFY_INFO_DATA *data,
2980 print_queue_struct *queue,
2981 NT_PRINTER_INFO_LEVEL *printer,
2982 TALLOC_CTX *mem_ctx)
2984 smb_ucs2_t *temp = NULL;
2985 uint32 len;
2987 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
2988 if (len == (uint32)-1) {
2989 len = 0;
2992 data->notify_data.data.length = len;
2993 if (len) {
2994 data->notify_data.data.string = (uint16 *)temp;
2995 } else {
2996 data->notify_data.data.string = NULL;
3000 /*******************************************************************
3001 * fill a notify_info_data with the data type
3002 * jfm:xxxx always send RAW as data type
3003 ********************************************************************/
3005 void spoolss_notify_datatype(int snum,
3006 SPOOL_NOTIFY_INFO_DATA *data,
3007 print_queue_struct *queue,
3008 NT_PRINTER_INFO_LEVEL *printer,
3009 TALLOC_CTX *mem_ctx)
3011 smb_ucs2_t *temp = NULL;
3012 uint32 len;
3014 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3015 if (len == (uint32)-1) {
3016 len = 0;
3019 data->notify_data.data.length = len;
3020 if (len) {
3021 data->notify_data.data.string = (uint16 *)temp;
3022 } else {
3023 data->notify_data.data.string = NULL;
3027 /*******************************************************************
3028 * fill a notify_info_data with the security descriptor
3029 * jfm:xxxx send an null pointer to say no security desc
3030 * have to implement security before !
3031 ********************************************************************/
3033 static void spoolss_notify_security_desc(int snum,
3034 SPOOL_NOTIFY_INFO_DATA *data,
3035 print_queue_struct *queue,
3036 NT_PRINTER_INFO_LEVEL *printer,
3037 TALLOC_CTX *mem_ctx)
3039 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3040 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3043 /*******************************************************************
3044 * fill a notify_info_data with the attributes
3045 * jfm:xxxx a samba printer is always shared
3046 ********************************************************************/
3048 void spoolss_notify_attributes(int snum,
3049 SPOOL_NOTIFY_INFO_DATA *data,
3050 print_queue_struct *queue,
3051 NT_PRINTER_INFO_LEVEL *printer,
3052 TALLOC_CTX *mem_ctx)
3054 data->notify_data.value[0] = printer->info_2->attributes;
3055 data->notify_data.value[1] = 0;
3058 /*******************************************************************
3059 * fill a notify_info_data with the priority
3060 ********************************************************************/
3062 static void spoolss_notify_priority(int snum,
3063 SPOOL_NOTIFY_INFO_DATA *data,
3064 print_queue_struct *queue,
3065 NT_PRINTER_INFO_LEVEL *printer,
3066 TALLOC_CTX *mem_ctx)
3068 data->notify_data.value[0] = printer->info_2->priority;
3069 data->notify_data.value[1] = 0;
3072 /*******************************************************************
3073 * fill a notify_info_data with the default priority
3074 ********************************************************************/
3076 static void spoolss_notify_default_priority(int snum,
3077 SPOOL_NOTIFY_INFO_DATA *data,
3078 print_queue_struct *queue,
3079 NT_PRINTER_INFO_LEVEL *printer,
3080 TALLOC_CTX *mem_ctx)
3082 data->notify_data.value[0] = printer->info_2->default_priority;
3083 data->notify_data.value[1] = 0;
3086 /*******************************************************************
3087 * fill a notify_info_data with the start time
3088 ********************************************************************/
3090 static void spoolss_notify_start_time(int snum,
3091 SPOOL_NOTIFY_INFO_DATA *data,
3092 print_queue_struct *queue,
3093 NT_PRINTER_INFO_LEVEL *printer,
3094 TALLOC_CTX *mem_ctx)
3096 data->notify_data.value[0] = printer->info_2->starttime;
3097 data->notify_data.value[1] = 0;
3100 /*******************************************************************
3101 * fill a notify_info_data with the until time
3102 ********************************************************************/
3104 static void spoolss_notify_until_time(int snum,
3105 SPOOL_NOTIFY_INFO_DATA *data,
3106 print_queue_struct *queue,
3107 NT_PRINTER_INFO_LEVEL *printer,
3108 TALLOC_CTX *mem_ctx)
3110 data->notify_data.value[0] = printer->info_2->untiltime;
3111 data->notify_data.value[1] = 0;
3114 /*******************************************************************
3115 * fill a notify_info_data with the status
3116 ********************************************************************/
3118 static void spoolss_notify_status(int snum,
3119 SPOOL_NOTIFY_INFO_DATA *data,
3120 print_queue_struct *queue,
3121 NT_PRINTER_INFO_LEVEL *printer,
3122 TALLOC_CTX *mem_ctx)
3124 print_status_struct status;
3126 print_queue_length(snum, &status);
3127 data->notify_data.value[0]=(uint32) status.status;
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with the number of jobs queued
3133 ********************************************************************/
3135 void spoolss_notify_cjobs(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 data->notify_data.value[0] = print_queue_length(snum, NULL);
3142 data->notify_data.value[1] = 0;
3145 /*******************************************************************
3146 * fill a notify_info_data with the average ppm
3147 ********************************************************************/
3149 static void spoolss_notify_average_ppm(int snum,
3150 SPOOL_NOTIFY_INFO_DATA *data,
3151 print_queue_struct *queue,
3152 NT_PRINTER_INFO_LEVEL *printer,
3153 TALLOC_CTX *mem_ctx)
3155 /* always respond 8 pages per minutes */
3156 /* a little hard ! */
3157 data->notify_data.value[0] = printer->info_2->averageppm;
3158 data->notify_data.value[1] = 0;
3161 /*******************************************************************
3162 * fill a notify_info_data with username
3163 ********************************************************************/
3165 static void spoolss_notify_username(int snum,
3166 SPOOL_NOTIFY_INFO_DATA *data,
3167 print_queue_struct *queue,
3168 NT_PRINTER_INFO_LEVEL *printer,
3169 TALLOC_CTX *mem_ctx)
3171 smb_ucs2_t *temp = NULL;
3172 uint32 len;
3174 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3175 if (len == (uint32)-1) {
3176 len = 0;
3179 data->notify_data.data.length = len;
3180 if (len) {
3181 data->notify_data.data.string = (uint16 *)temp;
3182 } else {
3183 data->notify_data.data.string = NULL;
3187 /*******************************************************************
3188 * fill a notify_info_data with job status
3189 ********************************************************************/
3191 static void spoolss_notify_job_status(int snum,
3192 SPOOL_NOTIFY_INFO_DATA *data,
3193 print_queue_struct *queue,
3194 NT_PRINTER_INFO_LEVEL *printer,
3195 TALLOC_CTX *mem_ctx)
3197 data->notify_data.value[0]=nt_printj_status(queue->status);
3198 data->notify_data.value[1] = 0;
3201 /*******************************************************************
3202 * fill a notify_info_data with job name
3203 ********************************************************************/
3205 static void spoolss_notify_job_name(int snum,
3206 SPOOL_NOTIFY_INFO_DATA *data,
3207 print_queue_struct *queue,
3208 NT_PRINTER_INFO_LEVEL *printer,
3209 TALLOC_CTX *mem_ctx)
3211 smb_ucs2_t *temp = NULL;
3212 uint32 len;
3214 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3215 if (len == (uint32)-1) {
3216 len = 0;
3219 data->notify_data.data.length = len;
3220 if (len) {
3221 data->notify_data.data.string = (uint16 *)temp;
3222 } else {
3223 data->notify_data.data.string = NULL;
3227 /*******************************************************************
3228 * fill a notify_info_data with job status
3229 ********************************************************************/
3231 static void spoolss_notify_job_status_string(int snum,
3232 SPOOL_NOTIFY_INFO_DATA *data,
3233 print_queue_struct *queue,
3234 NT_PRINTER_INFO_LEVEL *printer,
3235 TALLOC_CTX *mem_ctx)
3238 * Now we're returning job status codes we just return a "" here. JRA.
3241 const char *p = "";
3242 smb_ucs2_t *temp = NULL;
3243 uint32 len;
3245 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3246 p = "unknown";
3248 switch (queue->status) {
3249 case LPQ_QUEUED:
3250 p = "Queued";
3251 break;
3252 case LPQ_PAUSED:
3253 p = ""; /* NT provides the paused string */
3254 break;
3255 case LPQ_SPOOLING:
3256 p = "Spooling";
3257 break;
3258 case LPQ_PRINTING:
3259 p = "Printing";
3260 break;
3262 #endif /* NO LONGER NEEDED. */
3264 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3265 if (len == (uint32)-1) {
3266 len = 0;
3269 data->notify_data.data.length = len;
3270 if (len) {
3271 data->notify_data.data.string = (uint16 *)temp;
3272 } else {
3273 data->notify_data.data.string = NULL;
3277 /*******************************************************************
3278 * fill a notify_info_data with job time
3279 ********************************************************************/
3281 static void spoolss_notify_job_time(int snum,
3282 SPOOL_NOTIFY_INFO_DATA *data,
3283 print_queue_struct *queue,
3284 NT_PRINTER_INFO_LEVEL *printer,
3285 TALLOC_CTX *mem_ctx)
3287 data->notify_data.value[0]=0x0;
3288 data->notify_data.value[1]=0;
3291 /*******************************************************************
3292 * fill a notify_info_data with job size
3293 ********************************************************************/
3295 static void spoolss_notify_job_size(int snum,
3296 SPOOL_NOTIFY_INFO_DATA *data,
3297 print_queue_struct *queue,
3298 NT_PRINTER_INFO_LEVEL *printer,
3299 TALLOC_CTX *mem_ctx)
3301 data->notify_data.value[0]=queue->size;
3302 data->notify_data.value[1]=0;
3305 /*******************************************************************
3306 * fill a notify_info_data with page info
3307 ********************************************************************/
3308 static void spoolss_notify_total_pages(int snum,
3309 SPOOL_NOTIFY_INFO_DATA *data,
3310 print_queue_struct *queue,
3311 NT_PRINTER_INFO_LEVEL *printer,
3312 TALLOC_CTX *mem_ctx)
3314 data->notify_data.value[0]=queue->page_count;
3315 data->notify_data.value[1]=0;
3318 /*******************************************************************
3319 * fill a notify_info_data with pages printed info.
3320 ********************************************************************/
3321 static void spoolss_notify_pages_printed(int snum,
3322 SPOOL_NOTIFY_INFO_DATA *data,
3323 print_queue_struct *queue,
3324 NT_PRINTER_INFO_LEVEL *printer,
3325 TALLOC_CTX *mem_ctx)
3327 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3328 data->notify_data.value[1]=0;
3331 /*******************************************************************
3332 Fill a notify_info_data with job position.
3333 ********************************************************************/
3335 static void spoolss_notify_job_position(int snum,
3336 SPOOL_NOTIFY_INFO_DATA *data,
3337 print_queue_struct *queue,
3338 NT_PRINTER_INFO_LEVEL *printer,
3339 TALLOC_CTX *mem_ctx)
3341 data->notify_data.value[0]=queue->job;
3342 data->notify_data.value[1]=0;
3345 /*******************************************************************
3346 Fill a notify_info_data with submitted time.
3347 ********************************************************************/
3349 static void spoolss_notify_submitted_time(int snum,
3350 SPOOL_NOTIFY_INFO_DATA *data,
3351 print_queue_struct *queue,
3352 NT_PRINTER_INFO_LEVEL *printer,
3353 TALLOC_CTX *mem_ctx)
3355 struct tm *t;
3356 uint32 len;
3357 SYSTEMTIME st;
3358 char *p;
3360 t=gmtime(&queue->time);
3362 len = sizeof(SYSTEMTIME);
3364 data->notify_data.data.length = len;
3365 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3367 if (!data->notify_data.data.string) {
3368 data->notify_data.data.length = 0;
3369 return;
3372 make_systemtime(&st, t);
3375 * Systemtime must be linearized as a set of UINT16's.
3376 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3379 p = (char *)data->notify_data.data.string;
3380 SSVAL(p, 0, st.year);
3381 SSVAL(p, 2, st.month);
3382 SSVAL(p, 4, st.dayofweek);
3383 SSVAL(p, 6, st.day);
3384 SSVAL(p, 8, st.hour);
3385 SSVAL(p, 10, st.minute);
3386 SSVAL(p, 12, st.second);
3387 SSVAL(p, 14, st.milliseconds);
3390 struct s_notify_info_data_table
3392 uint16 type;
3393 uint16 field;
3394 const char *name;
3395 uint32 size;
3396 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3397 print_queue_struct *queue,
3398 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3401 /* A table describing the various print notification constants and
3402 whether the notification data is a pointer to a variable sized
3403 buffer, a one value uint32 or a two value uint32. */
3405 static const struct s_notify_info_data_table notify_info_data_table[] =
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3456 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3459 /*******************************************************************
3460 Return the size of info_data structure.
3461 ********************************************************************/
3463 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3465 int i=0;
3467 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3468 if ( (notify_info_data_table[i].type == type)
3469 && (notify_info_data_table[i].field == field) ) {
3470 switch(notify_info_data_table[i].size) {
3471 case NOTIFY_ONE_VALUE:
3472 case NOTIFY_TWO_VALUE:
3473 return 1;
3474 case NOTIFY_STRING:
3475 return 2;
3477 /* The only pointer notify data I have seen on
3478 the wire is the submitted time and this has
3479 the notify size set to 4. -tpot */
3481 case NOTIFY_POINTER:
3482 return 4;
3484 case NOTIFY_SECDESC:
3485 return 5;
3490 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3492 return 0;
3495 /*******************************************************************
3496 Return the type of notify_info_data.
3497 ********************************************************************/
3499 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3501 uint32 i=0;
3503 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3504 if (notify_info_data_table[i].type == type &&
3505 notify_info_data_table[i].field == field)
3506 return notify_info_data_table[i].size;
3509 return 0;
3512 /****************************************************************************
3513 ****************************************************************************/
3515 static bool search_notify(uint16 type, uint16 field, int *value)
3517 int i;
3519 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3520 if (notify_info_data_table[i].type == type &&
3521 notify_info_data_table[i].field == field &&
3522 notify_info_data_table[i].fn != NULL) {
3523 *value = i;
3524 return True;
3528 return False;
3531 /****************************************************************************
3532 ****************************************************************************/
3534 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3536 info_data->type = type;
3537 info_data->field = field;
3538 info_data->reserved = 0;
3540 info_data->size = size_of_notify_info_data(type, field);
3541 info_data->enc_type = type_of_notify_info_data(type, field);
3543 info_data->id = id;
3546 /*******************************************************************
3548 * fill a notify_info struct with info asked
3550 ********************************************************************/
3552 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3553 snum, SPOOL_NOTIFY_OPTION_TYPE
3554 *option_type, uint32 id,
3555 TALLOC_CTX *mem_ctx)
3557 int field_num,j;
3558 uint16 type;
3559 uint16 field;
3561 SPOOL_NOTIFY_INFO_DATA *current_data;
3562 NT_PRINTER_INFO_LEVEL *printer = NULL;
3563 print_queue_struct *queue=NULL;
3565 type=option_type->type;
3567 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3568 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3569 option_type->count, lp_servicename(snum)));
3571 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3572 return False;
3574 for(field_num=0; field_num<option_type->count; field_num++) {
3575 field = option_type->fields[field_num];
3577 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3579 if (!search_notify(type, field, &j) )
3580 continue;
3582 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3583 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3584 free_a_printer(&printer, 2);
3585 return False;
3588 current_data = &info->data[info->count];
3590 construct_info_data(current_data, type, field, id);
3592 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3593 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3595 notify_info_data_table[j].fn(snum, current_data, queue,
3596 printer, mem_ctx);
3598 info->count++;
3601 free_a_printer(&printer, 2);
3602 return True;
3605 /*******************************************************************
3607 * fill a notify_info struct with info asked
3609 ********************************************************************/
3611 static bool construct_notify_jobs_info(print_queue_struct *queue,
3612 SPOOL_NOTIFY_INFO *info,
3613 NT_PRINTER_INFO_LEVEL *printer,
3614 int snum, SPOOL_NOTIFY_OPTION_TYPE
3615 *option_type, uint32 id,
3616 TALLOC_CTX *mem_ctx)
3618 int field_num,j;
3619 uint16 type;
3620 uint16 field;
3622 SPOOL_NOTIFY_INFO_DATA *current_data;
3624 DEBUG(4,("construct_notify_jobs_info\n"));
3626 type = option_type->type;
3628 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3629 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3630 option_type->count));
3632 for(field_num=0; field_num<option_type->count; field_num++) {
3633 field = option_type->fields[field_num];
3635 if (!search_notify(type, field, &j) )
3636 continue;
3638 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3639 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3640 return False;
3643 current_data=&(info->data[info->count]);
3645 construct_info_data(current_data, type, field, id);
3646 notify_info_data_table[j].fn(snum, current_data, queue,
3647 printer, mem_ctx);
3648 info->count++;
3651 return True;
3655 * JFM: The enumeration is not that simple, it's even non obvious.
3657 * let's take an example: I want to monitor the PRINTER SERVER for
3658 * the printer's name and the number of jobs currently queued.
3659 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3660 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3662 * I have 3 printers on the back of my server.
3664 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3665 * structures.
3666 * Number Data Id
3667 * 1 printer 1 name 1
3668 * 2 printer 1 cjob 1
3669 * 3 printer 2 name 2
3670 * 4 printer 2 cjob 2
3671 * 5 printer 3 name 3
3672 * 6 printer 3 name 3
3674 * that's the print server case, the printer case is even worse.
3677 /*******************************************************************
3679 * enumerate all printers on the printserver
3680 * fill a notify_info struct with info asked
3682 ********************************************************************/
3684 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3685 SPOOL_NOTIFY_INFO *info,
3686 TALLOC_CTX *mem_ctx)
3688 int snum;
3689 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3690 int n_services=lp_numservices();
3691 int i;
3692 SPOOL_NOTIFY_OPTION *option;
3693 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3695 DEBUG(4,("printserver_notify_info\n"));
3697 if (!Printer)
3698 return WERR_BADFID;
3700 option=Printer->notify.option;
3701 info->version=2;
3702 info->data=NULL;
3703 info->count=0;
3705 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3706 sending a ffpcn() request first */
3708 if ( !option )
3709 return WERR_BADFID;
3711 for (i=0; i<option->count; i++) {
3712 option_type=&(option->ctr.type[i]);
3714 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3715 continue;
3717 for (snum=0; snum<n_services; snum++)
3719 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3720 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3724 #if 0
3726 * Debugging information, don't delete.
3729 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3730 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3731 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3733 for (i=0; i<info->count; i++) {
3734 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3735 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3736 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3738 #endif
3740 return WERR_OK;
3743 /*******************************************************************
3745 * fill a notify_info struct with info asked
3747 ********************************************************************/
3749 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3750 TALLOC_CTX *mem_ctx)
3752 int snum;
3753 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3754 int i;
3755 uint32 id;
3756 SPOOL_NOTIFY_OPTION *option;
3757 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3758 int count,j;
3759 print_queue_struct *queue=NULL;
3760 print_status_struct status;
3762 DEBUG(4,("printer_notify_info\n"));
3764 if (!Printer)
3765 return WERR_BADFID;
3767 option=Printer->notify.option;
3768 id = 0x0;
3769 info->version=2;
3770 info->data=NULL;
3771 info->count=0;
3773 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3774 sending a ffpcn() request first */
3776 if ( !option )
3777 return WERR_BADFID;
3779 get_printer_snum(p, hnd, &snum, NULL);
3781 for (i=0; i<option->count; i++) {
3782 option_type=&option->ctr.type[i];
3784 switch ( option_type->type ) {
3785 case PRINTER_NOTIFY_TYPE:
3786 if(construct_notify_printer_info(Printer, info, snum,
3787 option_type, id,
3788 mem_ctx))
3789 id--;
3790 break;
3792 case JOB_NOTIFY_TYPE: {
3793 NT_PRINTER_INFO_LEVEL *printer = NULL;
3795 count = print_queue_status(snum, &queue, &status);
3797 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3798 goto done;
3800 for (j=0; j<count; j++) {
3801 construct_notify_jobs_info(&queue[j], info,
3802 printer, snum,
3803 option_type,
3804 queue[j].job,
3805 mem_ctx);
3808 free_a_printer(&printer, 2);
3810 done:
3811 SAFE_FREE(queue);
3812 break;
3818 * Debugging information, don't delete.
3821 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3822 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3823 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3825 for (i=0; i<info->count; i++) {
3826 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3827 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3828 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3831 return WERR_OK;
3834 /********************************************************************
3835 * spoolss_rfnpcnex
3836 ********************************************************************/
3838 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3840 POLICY_HND *handle = &q_u->handle;
3841 SPOOL_NOTIFY_INFO *info = &r_u->info;
3843 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3844 WERROR result = WERR_BADFID;
3846 /* we always have a NOTIFY_INFO struct */
3847 r_u->info_ptr=0x1;
3849 if (!Printer) {
3850 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3851 OUR_HANDLE(handle)));
3852 goto done;
3855 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3858 * We are now using the change value, and
3859 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3860 * I don't have a global notification system, I'm sending back all the
3861 * informations even when _NOTHING_ has changed.
3864 /* We need to keep track of the change value to send back in
3865 RRPCN replies otherwise our updates are ignored. */
3867 Printer->notify.fnpcn = True;
3869 if (Printer->notify.client_connected) {
3870 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3871 Printer->notify.change = q_u->change;
3874 /* just ignore the SPOOL_NOTIFY_OPTION */
3876 switch (Printer->printer_type) {
3877 case SPLHND_SERVER:
3878 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3879 break;
3881 case SPLHND_PRINTER:
3882 result = printer_notify_info(p, handle, info, p->mem_ctx);
3883 break;
3886 Printer->notify.fnpcn = False;
3888 done:
3889 return result;
3892 /********************************************************************
3893 * construct_printer_info_0
3894 * fill a printer_info_0 struct
3895 ********************************************************************/
3897 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3899 char *chaine = NULL;
3900 int count;
3901 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3902 counter_printer_0 *session_counter;
3903 uint32 global_counter;
3904 struct tm *t;
3905 time_t setuptime;
3906 print_status_struct status;
3907 TALLOC_CTX *ctx = talloc_tos();
3909 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3910 return False;
3912 init_unistr(&printer->printername, ntprinter->info_2->printername);
3914 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3915 if (!chaine) {
3916 free_a_printer(&ntprinter,2);
3917 return false;
3920 count = print_queue_length(snum, &status);
3922 /* check if we already have a counter for this printer */
3923 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3924 if (session_counter->snum == snum)
3925 break;
3928 init_unistr(&printer->servername, chaine);
3930 /* it's the first time, add it to the list */
3931 if (session_counter==NULL) {
3932 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3933 free_a_printer(&ntprinter, 2);
3934 return False;
3936 ZERO_STRUCTP(session_counter);
3937 session_counter->snum=snum;
3938 session_counter->counter=0;
3939 DLIST_ADD(counter_list, session_counter);
3942 /* increment it */
3943 session_counter->counter++;
3945 /* JFM:
3946 * the global_counter should be stored in a TDB as it's common to all the clients
3947 * and should be zeroed on samba startup
3949 global_counter=session_counter->counter;
3950 printer->cjobs = count;
3951 printer->total_jobs = 0;
3952 printer->total_bytes = 0;
3954 setuptime = (time_t)ntprinter->info_2->setuptime;
3955 t=gmtime(&setuptime);
3957 printer->year = t->tm_year+1900;
3958 printer->month = t->tm_mon+1;
3959 printer->dayofweek = t->tm_wday;
3960 printer->day = t->tm_mday;
3961 printer->hour = t->tm_hour;
3962 printer->minute = t->tm_min;
3963 printer->second = t->tm_sec;
3964 printer->milliseconds = 0;
3966 printer->global_counter = global_counter;
3967 printer->total_pages = 0;
3969 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3970 printer->major_version = 0x0005; /* NT 5 */
3971 printer->build_version = 0x0893; /* build 2195 */
3973 printer->unknown7 = 0x1;
3974 printer->unknown8 = 0x0;
3975 printer->unknown9 = 0x0;
3976 printer->session_counter = session_counter->counter;
3977 printer->unknown11 = 0x0;
3978 printer->printer_errors = 0x0; /* number of print failure */
3979 printer->unknown13 = 0x0;
3980 printer->unknown14 = 0x1;
3981 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3982 printer->unknown16 = 0x0;
3983 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3984 printer->unknown18 = 0x0;
3985 printer->status = nt_printq_status(status.status);
3986 printer->unknown20 = 0x0;
3987 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3988 printer->unknown22 = 0x0;
3989 printer->unknown23 = 0x6; /* 6 ???*/
3990 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3991 printer->unknown25 = 0;
3992 printer->unknown26 = 0;
3993 printer->unknown27 = 0;
3994 printer->unknown28 = 0;
3995 printer->unknown29 = 0;
3997 free_a_printer(&ntprinter,2);
3998 return (True);
4001 /********************************************************************
4002 * construct_printer_info_1
4003 * fill a printer_info_1 struct
4004 ********************************************************************/
4005 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4007 char *chaine = NULL;
4008 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4009 TALLOC_CTX *ctx = talloc_tos();
4011 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4012 return false;
4014 printer->flags=flags;
4016 if (*ntprinter->info_2->comment == '\0') {
4017 init_unistr(&printer->comment, lp_comment(snum));
4018 chaine = talloc_asprintf(ctx,
4019 "%s,%s,%s", ntprinter->info_2->printername,
4020 ntprinter->info_2->drivername, lp_comment(snum));
4022 else {
4023 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4024 chaine = talloc_asprintf(ctx,
4025 "%s,%s,%s", ntprinter->info_2->printername,
4026 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4029 if (!chaine) {
4030 free_a_printer(&ntprinter,2);
4031 return false;
4034 init_unistr(&printer->description, chaine);
4035 init_unistr(&printer->name, ntprinter->info_2->printername);
4037 free_a_printer(&ntprinter,2);
4039 return True;
4042 /****************************************************************************
4043 Free a DEVMODE struct.
4044 ****************************************************************************/
4046 static void free_dev_mode(DEVICEMODE *dev)
4048 if (dev == NULL)
4049 return;
4051 SAFE_FREE(dev->dev_private);
4052 SAFE_FREE(dev);
4056 /****************************************************************************
4057 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4058 should be valid upon entry
4059 ****************************************************************************/
4061 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4063 if ( !devmode || !ntdevmode )
4064 return False;
4066 init_unistr(&devmode->devicename, ntdevmode->devicename);
4068 init_unistr(&devmode->formname, ntdevmode->formname);
4070 devmode->specversion = ntdevmode->specversion;
4071 devmode->driverversion = ntdevmode->driverversion;
4072 devmode->size = ntdevmode->size;
4073 devmode->driverextra = ntdevmode->driverextra;
4074 devmode->fields = ntdevmode->fields;
4076 devmode->orientation = ntdevmode->orientation;
4077 devmode->papersize = ntdevmode->papersize;
4078 devmode->paperlength = ntdevmode->paperlength;
4079 devmode->paperwidth = ntdevmode->paperwidth;
4080 devmode->scale = ntdevmode->scale;
4081 devmode->copies = ntdevmode->copies;
4082 devmode->defaultsource = ntdevmode->defaultsource;
4083 devmode->printquality = ntdevmode->printquality;
4084 devmode->color = ntdevmode->color;
4085 devmode->duplex = ntdevmode->duplex;
4086 devmode->yresolution = ntdevmode->yresolution;
4087 devmode->ttoption = ntdevmode->ttoption;
4088 devmode->collate = ntdevmode->collate;
4089 devmode->icmmethod = ntdevmode->icmmethod;
4090 devmode->icmintent = ntdevmode->icmintent;
4091 devmode->mediatype = ntdevmode->mediatype;
4092 devmode->dithertype = ntdevmode->dithertype;
4094 if (ntdevmode->nt_dev_private != NULL) {
4095 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4096 return False;
4099 return True;
4102 /****************************************************************************
4103 Create a DEVMODE struct. Returns malloced memory.
4104 ****************************************************************************/
4106 DEVICEMODE *construct_dev_mode(const char *servicename)
4108 NT_PRINTER_INFO_LEVEL *printer = NULL;
4109 DEVICEMODE *devmode = NULL;
4111 DEBUG(7,("construct_dev_mode\n"));
4113 DEBUGADD(8,("getting printer characteristics\n"));
4115 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4116 return NULL;
4118 if ( !printer->info_2->devmode ) {
4119 DEBUG(5, ("BONG! There was no device mode!\n"));
4120 goto done;
4123 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4124 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4125 goto done;
4128 ZERO_STRUCTP(devmode);
4130 DEBUGADD(8,("loading DEVICEMODE\n"));
4132 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4133 free_dev_mode( devmode );
4134 devmode = NULL;
4137 done:
4138 free_a_printer(&printer,2);
4140 return devmode;
4143 /********************************************************************
4144 * construct_printer_info_2
4145 * fill a printer_info_2 struct
4146 ********************************************************************/
4148 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4150 int count;
4151 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4153 print_status_struct status;
4155 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4156 return False;
4158 count = print_queue_length(snum, &status);
4160 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4161 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4162 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4163 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4164 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4166 if (*ntprinter->info_2->comment == '\0')
4167 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4168 else
4169 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4171 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4172 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4173 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4174 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4175 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4177 printer->attributes = ntprinter->info_2->attributes;
4179 printer->priority = ntprinter->info_2->priority; /* priority */
4180 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4181 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4182 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4183 printer->status = nt_printq_status(status.status); /* status */
4184 printer->cjobs = count; /* jobs */
4185 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4187 if ( !(printer->devmode = construct_dev_mode(
4188 lp_const_servicename(snum))) )
4189 DEBUG(8, ("Returning NULL Devicemode!\n"));
4191 printer->secdesc = NULL;
4193 if ( ntprinter->info_2->secdesc_buf
4194 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4196 /* don't use talloc_steal() here unless you do a deep steal of all
4197 the SEC_DESC members */
4199 printer->secdesc = dup_sec_desc( talloc_tos(),
4200 ntprinter->info_2->secdesc_buf->sd );
4203 free_a_printer(&ntprinter, 2);
4205 return True;
4208 /********************************************************************
4209 * construct_printer_info_3
4210 * fill a printer_info_3 struct
4211 ********************************************************************/
4213 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4215 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4216 PRINTER_INFO_3 *printer = NULL;
4218 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4219 return False;
4221 *pp_printer = NULL;
4222 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4223 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4224 free_a_printer(&ntprinter, 2);
4225 return False;
4228 ZERO_STRUCTP(printer);
4230 /* These are the components of the SD we are returning. */
4232 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4233 /* don't use talloc_steal() here unless you do a deep steal of all
4234 the SEC_DESC members */
4236 printer->secdesc = dup_sec_desc( talloc_tos(),
4237 ntprinter->info_2->secdesc_buf->sd );
4240 free_a_printer(&ntprinter, 2);
4242 *pp_printer = printer;
4243 return True;
4246 /********************************************************************
4247 * construct_printer_info_4
4248 * fill a printer_info_4 struct
4249 ********************************************************************/
4251 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4253 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4255 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4256 return False;
4258 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4259 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4260 printer->attributes = ntprinter->info_2->attributes;
4262 free_a_printer(&ntprinter, 2);
4263 return True;
4266 /********************************************************************
4267 * construct_printer_info_5
4268 * fill a printer_info_5 struct
4269 ********************************************************************/
4271 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4273 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4275 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4276 return False;
4278 init_unistr(&printer->printername, ntprinter->info_2->printername);
4279 init_unistr(&printer->portname, ntprinter->info_2->portname);
4280 printer->attributes = ntprinter->info_2->attributes;
4282 /* these two are not used by NT+ according to MSDN */
4284 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4285 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4287 free_a_printer(&ntprinter, 2);
4289 return True;
4292 /********************************************************************
4293 * construct_printer_info_6
4294 * fill a printer_info_6 struct
4295 ********************************************************************/
4297 static bool construct_printer_info_6(Printer_entry *print_hnd,
4298 PRINTER_INFO_6 *printer,
4299 int snum)
4301 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4302 int count;
4303 print_status_struct status;
4305 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4306 lp_const_servicename(snum))))
4307 return False;
4309 count = print_queue_length(snum, &status);
4311 printer->status = nt_printq_status(status.status);
4313 free_a_printer(&ntprinter, 2);
4315 return True;
4318 /********************************************************************
4319 * construct_printer_info_7
4320 * fill a printer_info_7 struct
4321 ********************************************************************/
4323 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4325 char *guid_str = NULL;
4326 struct GUID guid;
4328 if (is_printer_published(print_hnd, snum, &guid)) {
4329 if (asprintf(&guid_str, "{%s}",
4330 GUID_string(talloc_tos(), &guid)) == -1) {
4331 return false;
4333 strupper_m(guid_str);
4334 init_unistr(&printer->guid, guid_str);
4335 SAFE_FREE(guid_str);
4336 printer->action = SPOOL_DS_PUBLISH;
4337 } else {
4338 init_unistr(&printer->guid, "");
4339 printer->action = SPOOL_DS_UNPUBLISH;
4342 return True;
4345 /********************************************************************
4346 Spoolss_enumprinters.
4347 ********************************************************************/
4349 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4351 int snum;
4352 int i;
4353 int n_services=lp_numservices();
4354 PRINTER_INFO_1 *printers=NULL;
4355 PRINTER_INFO_1 current_prt;
4356 WERROR result = WERR_OK;
4358 DEBUG(4,("enum_all_printers_info_1\n"));
4360 for (snum=0; snum<n_services; snum++) {
4361 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4362 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4364 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4365 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4366 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4367 *returned=0;
4368 return WERR_NOMEM;
4370 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4372 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4373 (*returned)++;
4378 /* check the required size. */
4379 for (i=0; i<*returned; i++)
4380 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4382 if (*needed > offered) {
4383 result = WERR_INSUFFICIENT_BUFFER;
4384 goto out;
4387 if (!rpcbuf_alloc_size(buffer, *needed)) {
4388 result = WERR_NOMEM;
4389 goto out;
4392 /* fill the buffer with the structures */
4393 for (i=0; i<*returned; i++)
4394 smb_io_printer_info_1("", buffer, &printers[i], 0);
4396 out:
4397 /* clear memory */
4399 SAFE_FREE(printers);
4401 if ( !W_ERROR_IS_OK(result) )
4402 *returned = 0;
4404 return result;
4407 /********************************************************************
4408 enum_all_printers_info_1_local.
4409 *********************************************************************/
4411 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4413 DEBUG(4,("enum_all_printers_info_1_local\n"));
4415 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4418 /********************************************************************
4419 enum_all_printers_info_1_name.
4420 *********************************************************************/
4422 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4424 char *s = name;
4426 DEBUG(4,("enum_all_printers_info_1_name\n"));
4428 if ((name[0] == '\\') && (name[1] == '\\'))
4429 s = name + 2;
4431 if (is_myname_or_ipaddr(s)) {
4432 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4434 else
4435 return WERR_INVALID_NAME;
4438 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4439 /********************************************************************
4440 enum_all_printers_info_1_remote.
4441 *********************************************************************/
4443 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4445 PRINTER_INFO_1 *printer;
4446 fstring printername;
4447 fstring desc;
4448 fstring comment;
4449 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4450 WERROR result = WERR_OK;
4452 /* JFM: currently it's more a place holder than anything else.
4453 * In the spooler world there is a notion of server registration.
4454 * the print servers are registered on the PDC (in the same domain)
4456 * We should have a TDB here. The registration is done thru an
4457 * undocumented RPC call.
4460 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4461 return WERR_NOMEM;
4463 *returned=1;
4465 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4466 slprintf(desc, sizeof(desc)-1,"%s", name);
4467 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4469 init_unistr(&printer->description, desc);
4470 init_unistr(&printer->name, printername);
4471 init_unistr(&printer->comment, comment);
4472 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4474 /* check the required size. */
4475 *needed += spoolss_size_printer_info_1(printer);
4477 if (*needed > offered) {
4478 result = WERR_INSUFFICIENT_BUFFER;
4479 goto out;
4482 if (!rpcbuf_alloc_size(buffer, *needed)) {
4483 result = WERR_NOMEM;
4484 goto out;
4487 /* fill the buffer with the structures */
4488 smb_io_printer_info_1("", buffer, printer, 0);
4490 out:
4491 /* clear memory */
4492 SAFE_FREE(printer);
4494 if ( !W_ERROR_IS_OK(result) )
4495 *returned = 0;
4497 return result;
4500 #endif
4502 /********************************************************************
4503 enum_all_printers_info_1_network.
4504 *********************************************************************/
4506 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4508 char *s = name;
4510 DEBUG(4,("enum_all_printers_info_1_network\n"));
4512 /* If we respond to a enum_printers level 1 on our name with flags
4513 set to PRINTER_ENUM_REMOTE with a list of printers then these
4514 printers incorrectly appear in the APW browse list.
4515 Specifically the printers for the server appear at the workgroup
4516 level where all the other servers in the domain are
4517 listed. Windows responds to this call with a
4518 WERR_CAN_NOT_COMPLETE so we should do the same. */
4520 if (name[0] == '\\' && name[1] == '\\')
4521 s = name + 2;
4523 if (is_myname_or_ipaddr(s))
4524 return WERR_CAN_NOT_COMPLETE;
4526 return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4529 /********************************************************************
4530 * api_spoolss_enumprinters
4532 * called from api_spoolss_enumprinters (see this to understand)
4533 ********************************************************************/
4535 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4537 int snum;
4538 int i;
4539 int n_services=lp_numservices();
4540 PRINTER_INFO_2 *printers=NULL;
4541 PRINTER_INFO_2 current_prt;
4542 WERROR result = WERR_OK;
4544 *returned = 0;
4546 for (snum=0; snum<n_services; snum++) {
4547 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4548 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4550 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4551 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4552 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4553 *returned = 0;
4554 return WERR_NOMEM;
4557 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4559 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4561 (*returned)++;
4566 /* check the required size. */
4567 for (i=0; i<*returned; i++)
4568 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4570 if (*needed > offered) {
4571 result = WERR_INSUFFICIENT_BUFFER;
4572 goto out;
4575 if (!rpcbuf_alloc_size(buffer, *needed)) {
4576 result = WERR_NOMEM;
4577 goto out;
4580 /* fill the buffer with the structures */
4581 for (i=0; i<*returned; i++)
4582 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4584 out:
4585 /* clear memory */
4587 for (i=0; i<*returned; i++)
4588 free_devmode(printers[i].devmode);
4590 SAFE_FREE(printers);
4592 if ( !W_ERROR_IS_OK(result) )
4593 *returned = 0;
4595 return result;
4598 /********************************************************************
4599 * handle enumeration of printers at level 1
4600 ********************************************************************/
4602 static WERROR enumprinters_level1( uint32 flags, fstring name,
4603 RPC_BUFFER *buffer, uint32 offered,
4604 uint32 *needed, uint32 *returned)
4606 /* Not all the flags are equals */
4608 if (flags & PRINTER_ENUM_LOCAL)
4609 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4611 if (flags & PRINTER_ENUM_NAME)
4612 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4614 #if 0 /* JERRY - disabled for now */
4615 if (flags & PRINTER_ENUM_REMOTE)
4616 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4617 #endif
4619 if (flags & PRINTER_ENUM_NETWORK)
4620 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4622 return WERR_OK; /* NT4sp5 does that */
4625 /********************************************************************
4626 * handle enumeration of printers at level 2
4627 ********************************************************************/
4629 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4630 RPC_BUFFER *buffer, uint32 offered,
4631 uint32 *needed, uint32 *returned)
4633 if (flags & PRINTER_ENUM_LOCAL) {
4634 return enum_all_printers_info_2(buffer, offered, needed, returned);
4637 if (flags & PRINTER_ENUM_NAME) {
4638 if (is_myname_or_ipaddr(canon_servername(servername)))
4639 return enum_all_printers_info_2(buffer, offered, needed, returned);
4640 else
4641 return WERR_INVALID_NAME;
4644 if (flags & PRINTER_ENUM_REMOTE)
4645 return WERR_UNKNOWN_LEVEL;
4647 return WERR_OK;
4650 /********************************************************************
4651 * handle enumeration of printers at level 5
4652 ********************************************************************/
4654 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4655 RPC_BUFFER *buffer, uint32 offered,
4656 uint32 *needed, uint32 *returned)
4658 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4659 return WERR_OK;
4662 /********************************************************************
4663 * api_spoolss_enumprinters
4665 * called from api_spoolss_enumprinters (see this to understand)
4666 ********************************************************************/
4668 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4670 uint32 flags = q_u->flags;
4671 UNISTR2 *servername = &q_u->servername;
4672 uint32 level = q_u->level;
4673 RPC_BUFFER *buffer = NULL;
4674 uint32 offered = q_u->offered;
4675 uint32 *needed = &r_u->needed;
4676 uint32 *returned = &r_u->returned;
4678 fstring name;
4680 /* that's an [in out] buffer */
4682 if (!q_u->buffer && (offered!=0)) {
4683 return WERR_INVALID_PARAM;
4686 rpcbuf_move(q_u->buffer, &r_u->buffer);
4687 buffer = r_u->buffer;
4689 DEBUG(4,("_spoolss_enumprinters\n"));
4691 *needed=0;
4692 *returned=0;
4695 * Level 1:
4696 * flags==PRINTER_ENUM_NAME
4697 * if name=="" then enumerates all printers
4698 * if name!="" then enumerate the printer
4699 * flags==PRINTER_ENUM_REMOTE
4700 * name is NULL, enumerate printers
4701 * Level 2: name!="" enumerates printers, name can't be NULL
4702 * Level 3: doesn't exist
4703 * Level 4: does a local registry lookup
4704 * Level 5: same as Level 2
4707 unistr2_to_ascii(name, servername, sizeof(name));
4708 strupper_m(name);
4710 switch (level) {
4711 case 1:
4712 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4713 case 2:
4714 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4715 case 5:
4716 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4717 case 3:
4718 case 4:
4719 break;
4721 return WERR_UNKNOWN_LEVEL;
4724 /****************************************************************************
4725 ****************************************************************************/
4727 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4729 PRINTER_INFO_0 *printer=NULL;
4730 WERROR result = WERR_OK;
4732 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4733 return WERR_NOMEM;
4735 construct_printer_info_0(print_hnd, printer, snum);
4737 /* check the required size. */
4738 *needed += spoolss_size_printer_info_0(printer);
4740 if (*needed > offered) {
4741 result = WERR_INSUFFICIENT_BUFFER;
4742 goto out;
4745 if (!rpcbuf_alloc_size(buffer, *needed)) {
4746 result = WERR_NOMEM;
4747 goto out;
4750 /* fill the buffer with the structures */
4751 smb_io_printer_info_0("", buffer, printer, 0);
4753 out:
4754 /* clear memory */
4756 SAFE_FREE(printer);
4758 return result;
4761 /****************************************************************************
4762 ****************************************************************************/
4764 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4766 PRINTER_INFO_1 *printer=NULL;
4767 WERROR result = WERR_OK;
4769 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4770 return WERR_NOMEM;
4772 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4774 /* check the required size. */
4775 *needed += spoolss_size_printer_info_1(printer);
4777 if (*needed > offered) {
4778 result = WERR_INSUFFICIENT_BUFFER;
4779 goto out;
4782 if (!rpcbuf_alloc_size(buffer, *needed)) {
4783 result = WERR_NOMEM;
4784 goto out;
4787 /* fill the buffer with the structures */
4788 smb_io_printer_info_1("", buffer, printer, 0);
4790 out:
4791 /* clear memory */
4792 SAFE_FREE(printer);
4794 return result;
4797 /****************************************************************************
4798 ****************************************************************************/
4800 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4802 PRINTER_INFO_2 *printer=NULL;
4803 WERROR result = WERR_OK;
4805 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4806 return WERR_NOMEM;
4808 construct_printer_info_2(print_hnd, printer, snum);
4810 /* check the required size. */
4811 *needed += spoolss_size_printer_info_2(printer);
4813 if (*needed > offered) {
4814 result = WERR_INSUFFICIENT_BUFFER;
4815 goto out;
4818 if (!rpcbuf_alloc_size(buffer, *needed)) {
4819 result = WERR_NOMEM;
4820 goto out;
4823 /* fill the buffer with the structures */
4824 if (!smb_io_printer_info_2("", buffer, printer, 0))
4825 result = WERR_NOMEM;
4827 out:
4828 /* clear memory */
4829 free_printer_info_2(printer);
4831 return result;
4834 /****************************************************************************
4835 ****************************************************************************/
4837 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4839 PRINTER_INFO_3 *printer=NULL;
4840 WERROR result = WERR_OK;
4842 if (!construct_printer_info_3(print_hnd, &printer, snum))
4843 return WERR_NOMEM;
4845 /* check the required size. */
4846 *needed += spoolss_size_printer_info_3(printer);
4848 if (*needed > offered) {
4849 result = WERR_INSUFFICIENT_BUFFER;
4850 goto out;
4853 if (!rpcbuf_alloc_size(buffer, *needed)) {
4854 result = WERR_NOMEM;
4855 goto out;
4858 /* fill the buffer with the structures */
4859 smb_io_printer_info_3("", buffer, printer, 0);
4861 out:
4862 /* clear memory */
4863 free_printer_info_3(printer);
4865 return result;
4868 /****************************************************************************
4869 ****************************************************************************/
4871 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4873 PRINTER_INFO_4 *printer=NULL;
4874 WERROR result = WERR_OK;
4876 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4877 return WERR_NOMEM;
4879 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4880 SAFE_FREE(printer);
4881 return WERR_NOMEM;
4884 /* check the required size. */
4885 *needed += spoolss_size_printer_info_4(printer);
4887 if (*needed > offered) {
4888 result = WERR_INSUFFICIENT_BUFFER;
4889 goto out;
4892 if (!rpcbuf_alloc_size(buffer, *needed)) {
4893 result = WERR_NOMEM;
4894 goto out;
4897 /* fill the buffer with the structures */
4898 smb_io_printer_info_4("", buffer, printer, 0);
4900 out:
4901 /* clear memory */
4902 free_printer_info_4(printer);
4904 return result;
4907 /****************************************************************************
4908 ****************************************************************************/
4910 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4912 PRINTER_INFO_5 *printer=NULL;
4913 WERROR result = WERR_OK;
4915 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4916 return WERR_NOMEM;
4918 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4919 free_printer_info_5(printer);
4920 return WERR_NOMEM;
4923 /* check the required size. */
4924 *needed += spoolss_size_printer_info_5(printer);
4926 if (*needed > offered) {
4927 result = WERR_INSUFFICIENT_BUFFER;
4928 goto out;
4931 if (!rpcbuf_alloc_size(buffer, *needed)) {
4932 result = WERR_NOMEM;
4933 goto out;
4936 /* fill the buffer with the structures */
4937 smb_io_printer_info_5("", buffer, printer, 0);
4939 out:
4940 /* clear memory */
4941 free_printer_info_5(printer);
4943 return result;
4946 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4947 int snum,
4948 RPC_BUFFER *buffer, uint32 offered,
4949 uint32 *needed)
4951 PRINTER_INFO_6 *printer;
4952 WERROR result = WERR_OK;
4954 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4955 return WERR_NOMEM;
4958 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4959 free_printer_info_6(printer);
4960 return WERR_NOMEM;
4963 /* check the required size. */
4964 *needed += spoolss_size_printer_info_6(printer);
4966 if (*needed > offered) {
4967 result = WERR_INSUFFICIENT_BUFFER;
4968 goto out;
4971 if (!rpcbuf_alloc_size(buffer, *needed)) {
4972 result = WERR_NOMEM;
4973 goto out;
4976 /* fill the buffer with the structures */
4977 smb_io_printer_info_6("", buffer, printer, 0);
4979 out:
4980 /* clear memory */
4981 free_printer_info_6(printer);
4983 return result;
4986 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4988 PRINTER_INFO_7 *printer=NULL;
4989 WERROR result = WERR_OK;
4991 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4992 return WERR_NOMEM;
4994 if (!construct_printer_info_7(print_hnd, printer, snum)) {
4995 result = WERR_NOMEM;
4996 goto out;
4999 /* check the required size. */
5000 *needed += spoolss_size_printer_info_7(printer);
5002 if (*needed > offered) {
5003 result = WERR_INSUFFICIENT_BUFFER;
5004 goto out;
5007 if (!rpcbuf_alloc_size(buffer, *needed)) {
5008 result = WERR_NOMEM;
5009 goto out;
5013 /* fill the buffer with the structures */
5014 smb_io_printer_info_7("", buffer, printer, 0);
5016 out:
5017 /* clear memory */
5018 free_printer_info_7(printer);
5020 return result;
5023 /****************************************************************************
5024 ****************************************************************************/
5026 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5028 POLICY_HND *handle = &q_u->handle;
5029 uint32 level = q_u->level;
5030 RPC_BUFFER *buffer = NULL;
5031 uint32 offered = q_u->offered;
5032 uint32 *needed = &r_u->needed;
5033 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5035 int snum;
5037 /* that's an [in out] buffer */
5039 if (!q_u->buffer && (offered!=0)) {
5040 return WERR_INVALID_PARAM;
5043 rpcbuf_move(q_u->buffer, &r_u->buffer);
5044 buffer = r_u->buffer;
5046 *needed=0;
5048 if (!get_printer_snum(p, handle, &snum, NULL))
5049 return WERR_BADFID;
5051 switch (level) {
5052 case 0:
5053 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5054 case 1:
5055 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5056 case 2:
5057 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5058 case 3:
5059 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5060 case 4:
5061 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5062 case 5:
5063 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5064 case 6:
5065 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5066 case 7:
5067 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5069 return WERR_UNKNOWN_LEVEL;
5072 /********************************************************************
5073 * fill a DRIVER_INFO_1 struct
5074 ********************************************************************/
5076 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5078 init_unistr( &info->name, driver.info_3->name);
5081 /********************************************************************
5082 * construct_printer_driver_info_1
5083 ********************************************************************/
5085 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5087 NT_PRINTER_INFO_LEVEL *printer = NULL;
5088 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5090 ZERO_STRUCT(driver);
5092 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5093 return WERR_INVALID_PRINTER_NAME;
5095 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5096 free_a_printer(&printer, 2);
5097 return WERR_UNKNOWN_PRINTER_DRIVER;
5100 fill_printer_driver_info_1(info, driver, servername, architecture);
5102 free_a_printer(&printer,2);
5104 return WERR_OK;
5107 /********************************************************************
5108 * construct_printer_driver_info_2
5109 * fill a printer_info_2 struct
5110 ********************************************************************/
5112 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5114 TALLOC_CTX *ctx = talloc_tos();
5115 char *temp = NULL;
5116 const char *cservername = canon_servername(servername);
5118 info->version=driver.info_3->cversion;
5120 init_unistr( &info->name, driver.info_3->name );
5121 init_unistr( &info->architecture, driver.info_3->environment );
5123 if (strlen(driver.info_3->driverpath)) {
5124 temp = talloc_asprintf(ctx,
5125 "\\\\%s%s",
5126 cservername,
5127 driver.info_3->driverpath);
5128 init_unistr( &info->driverpath, temp );
5129 } else {
5130 init_unistr( &info->driverpath, "" );
5133 TALLOC_FREE(temp);
5134 if (strlen(driver.info_3->datafile)) {
5135 temp = talloc_asprintf(ctx,
5136 "\\\\%s%s",
5137 cservername,
5138 driver.info_3->datafile);
5139 init_unistr( &info->datafile, temp );
5140 } else
5141 init_unistr( &info->datafile, "" );
5143 TALLOC_FREE(temp);
5144 if (strlen(driver.info_3->configfile)) {
5145 temp = talloc_asprintf(ctx,
5146 "\\\\%s%s",
5147 cservername,
5148 driver.info_3->configfile);
5149 init_unistr( &info->configfile, temp );
5150 } else
5151 init_unistr( &info->configfile, "" );
5154 /********************************************************************
5155 * construct_printer_driver_info_2
5156 * fill a printer_info_2 struct
5157 ********************************************************************/
5159 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5161 NT_PRINTER_INFO_LEVEL *printer = NULL;
5162 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5164 ZERO_STRUCT(printer);
5165 ZERO_STRUCT(driver);
5167 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5168 return WERR_INVALID_PRINTER_NAME;
5170 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5171 free_a_printer(&printer, 2);
5172 return WERR_UNKNOWN_PRINTER_DRIVER;
5175 fill_printer_driver_info_2(info, driver, servername);
5177 free_a_printer(&printer,2);
5179 return WERR_OK;
5182 /********************************************************************
5183 * copy a strings array and convert to UNICODE
5185 * convert an array of ascii string to a UNICODE string
5186 ********************************************************************/
5188 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5190 int i=0;
5191 int j=0;
5192 const char *v;
5193 char *line = NULL;
5194 TALLOC_CTX *ctx = talloc_tos();
5196 DEBUG(6,("init_unistr_array\n"));
5197 *uni_array=NULL;
5199 while (true) {
5200 if ( !char_array ) {
5201 v = "";
5202 } else {
5203 v = char_array[i];
5204 if (!v)
5205 v = ""; /* hack to handle null lists */
5208 /* hack to allow this to be used in places other than when generating
5209 the list of dependent files */
5211 TALLOC_FREE(line);
5212 if ( servername ) {
5213 line = talloc_asprintf(ctx,
5214 "\\\\%s%s",
5215 canon_servername(servername),
5217 } else {
5218 line = talloc_strdup(ctx, v);
5221 if (!line) {
5222 SAFE_FREE(*uni_array);
5223 return 0;
5225 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5227 /* add one extra unit16 for the second terminating NULL */
5229 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5230 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5231 return 0;
5234 if ( !strlen(v) )
5235 break;
5237 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5238 i++;
5241 if (*uni_array) {
5242 /* special case for ""; we need to add both NULL's here */
5243 if (!j)
5244 (*uni_array)[j++]=0x0000;
5245 (*uni_array)[j]=0x0000;
5248 DEBUGADD(6,("last one:done\n"));
5250 /* return size of array in uint16's */
5252 return j+1;
5255 /********************************************************************
5256 * construct_printer_info_3
5257 * fill a printer_info_3 struct
5258 ********************************************************************/
5260 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5262 char *temp = NULL;
5263 TALLOC_CTX *ctx = talloc_tos();
5264 const char *cservername = canon_servername(servername);
5266 ZERO_STRUCTP(info);
5268 info->version=driver.info_3->cversion;
5270 init_unistr( &info->name, driver.info_3->name );
5271 init_unistr( &info->architecture, driver.info_3->environment );
5273 if (strlen(driver.info_3->driverpath)) {
5274 temp = talloc_asprintf(ctx,
5275 "\\\\%s%s",
5276 cservername,
5277 driver.info_3->driverpath);
5278 init_unistr( &info->driverpath, temp );
5279 } else
5280 init_unistr( &info->driverpath, "" );
5282 TALLOC_FREE(temp);
5283 if (strlen(driver.info_3->datafile)) {
5284 temp = talloc_asprintf(ctx,
5285 "\\\\%s%s",
5286 cservername,
5287 driver.info_3->datafile);
5288 init_unistr( &info->datafile, temp );
5289 } else
5290 init_unistr( &info->datafile, "" );
5292 TALLOC_FREE(temp);
5293 if (strlen(driver.info_3->configfile)) {
5294 temp = talloc_asprintf(ctx,
5295 "\\\\%s%s",
5296 cservername,
5297 driver.info_3->configfile);
5298 init_unistr( &info->configfile, temp );
5299 } else
5300 init_unistr( &info->configfile, "" );
5302 TALLOC_FREE(temp);
5303 if (strlen(driver.info_3->helpfile)) {
5304 temp = talloc_asprintf(ctx,
5305 "\\\\%s%s",
5306 cservername,
5307 driver.info_3->helpfile);
5308 init_unistr( &info->helpfile, temp );
5309 } else
5310 init_unistr( &info->helpfile, "" );
5312 TALLOC_FREE(temp);
5313 init_unistr( &info->monitorname, driver.info_3->monitorname );
5314 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5316 info->dependentfiles=NULL;
5317 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5320 /********************************************************************
5321 * construct_printer_info_3
5322 * fill a printer_info_3 struct
5323 ********************************************************************/
5325 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5327 NT_PRINTER_INFO_LEVEL *printer = NULL;
5328 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5329 WERROR status;
5330 ZERO_STRUCT(driver);
5332 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5333 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5334 if (!W_ERROR_IS_OK(status))
5335 return WERR_INVALID_PRINTER_NAME;
5337 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5338 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5340 #if 0 /* JERRY */
5343 * I put this code in during testing. Helpful when commenting out the
5344 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5345 * as win2k always queries the driver using an infor level of 6.
5346 * I've left it in (but ifdef'd out) because I'll probably
5347 * use it in experimentation again in the future. --jerry 22/01/2002
5350 if (!W_ERROR_IS_OK(status)) {
5352 * Is this a W2k client ?
5354 if (version == 3) {
5355 /* Yes - try again with a WinNT driver. */
5356 version = 2;
5357 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5358 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5360 #endif
5362 if (!W_ERROR_IS_OK(status)) {
5363 free_a_printer(&printer,2);
5364 return WERR_UNKNOWN_PRINTER_DRIVER;
5367 #if 0 /* JERRY */
5369 #endif
5372 fill_printer_driver_info_3(info, driver, servername);
5374 free_a_printer(&printer,2);
5376 return WERR_OK;
5379 /********************************************************************
5380 * construct_printer_info_6
5381 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5382 ********************************************************************/
5384 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5386 char *temp = NULL;
5387 fstring nullstr;
5388 TALLOC_CTX *ctx = talloc_tos();
5389 const char *cservername = canon_servername(servername);
5391 ZERO_STRUCTP(info);
5392 memset(&nullstr, '\0', sizeof(fstring));
5394 info->version=driver.info_3->cversion;
5396 init_unistr( &info->name, driver.info_3->name );
5397 init_unistr( &info->architecture, driver.info_3->environment );
5399 if (strlen(driver.info_3->driverpath)) {
5400 temp = talloc_asprintf(ctx,
5401 "\\\\%s%s",
5402 cservername,
5403 driver.info_3->driverpath);
5404 init_unistr( &info->driverpath, temp );
5405 } else
5406 init_unistr( &info->driverpath, "" );
5408 TALLOC_FREE(temp);
5409 if (strlen(driver.info_3->datafile)) {
5410 temp = talloc_asprintf(ctx,
5411 "\\\\%s%s",
5412 cservername,
5413 driver.info_3->datafile);
5414 init_unistr( &info->datafile, temp );
5415 } else
5416 init_unistr( &info->datafile, "" );
5418 TALLOC_FREE(temp);
5419 if (strlen(driver.info_3->configfile)) {
5420 temp = talloc_asprintf(ctx,
5421 "\\\\%s%s",
5422 cservername,
5423 driver.info_3->configfile);
5424 init_unistr( &info->configfile, temp );
5425 } else
5426 init_unistr( &info->configfile, "" );
5428 TALLOC_FREE(temp);
5429 if (strlen(driver.info_3->helpfile)) {
5430 temp = talloc_asprintf(ctx,
5431 "\\\\%s%s",
5432 cservername,
5433 driver.info_3->helpfile);
5434 init_unistr( &info->helpfile, temp );
5435 } else
5436 init_unistr( &info->helpfile, "" );
5438 TALLOC_FREE(temp);
5439 init_unistr( &info->monitorname, driver.info_3->monitorname );
5440 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5442 info->dependentfiles = NULL;
5443 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5445 info->previousdrivernames=NULL;
5446 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5448 info->driver_date=0;
5450 info->padding=0;
5451 info->driver_version_low=0;
5452 info->driver_version_high=0;
5454 init_unistr( &info->mfgname, "");
5455 init_unistr( &info->oem_url, "");
5456 init_unistr( &info->hardware_id, "");
5457 init_unistr( &info->provider, "");
5460 /********************************************************************
5461 * construct_printer_info_6
5462 * fill a printer_info_6 struct
5463 ********************************************************************/
5465 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5466 const char *servername, fstring architecture, uint32 version)
5468 NT_PRINTER_INFO_LEVEL *printer = NULL;
5469 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5470 WERROR status;
5472 ZERO_STRUCT(driver);
5474 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5476 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5478 if (!W_ERROR_IS_OK(status))
5479 return WERR_INVALID_PRINTER_NAME;
5481 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5483 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5485 if (!W_ERROR_IS_OK(status))
5488 * Is this a W2k client ?
5491 if (version < 3) {
5492 free_a_printer(&printer,2);
5493 return WERR_UNKNOWN_PRINTER_DRIVER;
5496 /* Yes - try again with a WinNT driver. */
5497 version = 2;
5498 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5499 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5500 if (!W_ERROR_IS_OK(status)) {
5501 free_a_printer(&printer,2);
5502 return WERR_UNKNOWN_PRINTER_DRIVER;
5506 fill_printer_driver_info_6(info, driver, servername);
5508 free_a_printer(&printer,2);
5509 free_a_printer_driver(driver, 3);
5511 return WERR_OK;
5514 /****************************************************************************
5515 ****************************************************************************/
5517 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5519 SAFE_FREE(info->dependentfiles);
5522 /****************************************************************************
5523 ****************************************************************************/
5525 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5527 SAFE_FREE(info->dependentfiles);
5530 /****************************************************************************
5531 ****************************************************************************/
5533 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5535 DRIVER_INFO_1 *info=NULL;
5536 WERROR result;
5538 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5539 return WERR_NOMEM;
5541 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5542 if (!W_ERROR_IS_OK(result))
5543 goto out;
5545 /* check the required size. */
5546 *needed += spoolss_size_printer_driver_info_1(info);
5548 if (*needed > offered) {
5549 result = WERR_INSUFFICIENT_BUFFER;
5550 goto out;
5553 if (!rpcbuf_alloc_size(buffer, *needed)) {
5554 result = WERR_NOMEM;
5555 goto out;
5558 /* fill the buffer with the structures */
5559 smb_io_printer_driver_info_1("", buffer, info, 0);
5561 out:
5562 /* clear memory */
5563 SAFE_FREE(info);
5565 return result;
5568 /****************************************************************************
5569 ****************************************************************************/
5571 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5573 DRIVER_INFO_2 *info=NULL;
5574 WERROR result;
5576 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5577 return WERR_NOMEM;
5579 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5580 if (!W_ERROR_IS_OK(result))
5581 goto out;
5583 /* check the required size. */
5584 *needed += spoolss_size_printer_driver_info_2(info);
5586 if (*needed > offered) {
5587 result = WERR_INSUFFICIENT_BUFFER;
5588 goto out;
5591 if (!rpcbuf_alloc_size(buffer, *needed)) {
5592 result = WERR_NOMEM;
5593 goto out;
5596 /* fill the buffer with the structures */
5597 smb_io_printer_driver_info_2("", buffer, info, 0);
5599 out:
5600 /* clear memory */
5601 SAFE_FREE(info);
5603 return result;
5606 /****************************************************************************
5607 ****************************************************************************/
5609 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5611 DRIVER_INFO_3 info;
5612 WERROR result;
5614 ZERO_STRUCT(info);
5616 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5617 if (!W_ERROR_IS_OK(result))
5618 goto out;
5620 /* check the required size. */
5621 *needed += spoolss_size_printer_driver_info_3(&info);
5623 if (*needed > offered) {
5624 result = WERR_INSUFFICIENT_BUFFER;
5625 goto out;
5628 if (!rpcbuf_alloc_size(buffer, *needed)) {
5629 result = WERR_NOMEM;
5630 goto out;
5633 /* fill the buffer with the structures */
5634 smb_io_printer_driver_info_3("", buffer, &info, 0);
5636 out:
5637 free_printer_driver_info_3(&info);
5639 return result;
5642 /****************************************************************************
5643 ****************************************************************************/
5645 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5647 DRIVER_INFO_6 info;
5648 WERROR result;
5650 ZERO_STRUCT(info);
5652 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5653 if (!W_ERROR_IS_OK(result))
5654 goto out;
5656 /* check the required size. */
5657 *needed += spoolss_size_printer_driver_info_6(&info);
5659 if (*needed > offered) {
5660 result = WERR_INSUFFICIENT_BUFFER;
5661 goto out;
5664 if (!rpcbuf_alloc_size(buffer, *needed)) {
5665 result = WERR_NOMEM;
5666 goto out;
5669 /* fill the buffer with the structures */
5670 smb_io_printer_driver_info_6("", buffer, &info, 0);
5672 out:
5673 free_printer_driver_info_6(&info);
5675 return result;
5678 /****************************************************************************
5679 ****************************************************************************/
5681 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5683 POLICY_HND *handle = &q_u->handle;
5684 UNISTR2 *uni_arch = &q_u->architecture;
5685 uint32 level = q_u->level;
5686 uint32 clientmajorversion = q_u->clientmajorversion;
5687 RPC_BUFFER *buffer = NULL;
5688 uint32 offered = q_u->offered;
5689 uint32 *needed = &r_u->needed;
5690 uint32 *servermajorversion = &r_u->servermajorversion;
5691 uint32 *serverminorversion = &r_u->serverminorversion;
5692 Printer_entry *printer;
5694 fstring servername;
5695 fstring architecture;
5696 int snum;
5698 /* that's an [in out] buffer */
5700 if (!q_u->buffer && (offered!=0)) {
5701 return WERR_INVALID_PARAM;
5704 rpcbuf_move(q_u->buffer, &r_u->buffer);
5705 buffer = r_u->buffer;
5707 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5709 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5710 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5711 return WERR_INVALID_PRINTER_NAME;
5714 *needed = 0;
5715 *servermajorversion = 0;
5716 *serverminorversion = 0;
5718 fstrcpy(servername, get_server_name( printer ));
5719 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5721 if (!get_printer_snum(p, handle, &snum, NULL))
5722 return WERR_BADFID;
5724 switch (level) {
5725 case 1:
5726 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5727 case 2:
5728 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5729 case 3:
5730 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5731 case 6:
5732 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5733 #if 0 /* JERRY */
5734 case 101:
5735 /* apparently this call is the equivalent of
5736 EnumPrinterDataEx() for the DsDriver key */
5737 break;
5738 #endif
5741 return WERR_UNKNOWN_LEVEL;
5745 /****************************************************************
5746 _spoolss_StartPagePrinter
5747 ****************************************************************/
5749 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5750 struct spoolss_StartPagePrinter *r)
5752 POLICY_HND *handle = r->in.handle;
5754 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5756 if (!Printer) {
5757 DEBUG(3,("_spoolss_StartPagePrinter: "
5758 "Error in startpageprinter printer handle\n"));
5759 return WERR_BADFID;
5762 Printer->page_started=True;
5763 return WERR_OK;
5766 /****************************************************************
5767 _spoolss_EndPagePrinter
5768 ****************************************************************/
5770 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5771 struct spoolss_EndPagePrinter *r)
5773 POLICY_HND *handle = r->in.handle;
5774 int snum;
5776 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5778 if (!Printer) {
5779 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5780 OUR_HANDLE(handle)));
5781 return WERR_BADFID;
5784 if (!get_printer_snum(p, handle, &snum, NULL))
5785 return WERR_BADFID;
5787 Printer->page_started=False;
5788 print_job_endpage(snum, Printer->jobid);
5790 return WERR_OK;
5793 /****************************************************************
5794 _spoolss_StartDocPrinter
5795 ****************************************************************/
5797 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5798 struct spoolss_StartDocPrinter *r)
5800 POLICY_HND *handle = r->in.handle;
5801 uint32_t *jobid = r->out.job_id;
5802 struct spoolss_DocumentInfo1 *info_1;
5803 int snum;
5804 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5806 if (!Printer) {
5807 DEBUG(2,("_spoolss_StartDocPrinter: "
5808 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5809 return WERR_BADFID;
5812 if (r->in.level != 1) {
5813 return WERR_UNKNOWN_LEVEL;
5816 info_1 = r->in.info.info1;
5819 * a nice thing with NT is it doesn't listen to what you tell it.
5820 * when asked to send _only_ RAW datas, it tries to send datas
5821 * in EMF format.
5823 * So I add checks like in NT Server ...
5826 if (info_1->datatype) {
5827 if (strcmp(info_1->datatype, "RAW") != 0) {
5828 (*jobid)=0;
5829 return WERR_INVALID_DATATYPE;
5833 /* get the share number of the printer */
5834 if (!get_printer_snum(p, handle, &snum, NULL)) {
5835 return WERR_BADFID;
5838 Printer->jobid = print_job_start(p->server_info, snum,
5839 CONST_DISCARD(char *,info_1->document_name),
5840 Printer->nt_devmode);
5842 /* An error occured in print_job_start() so return an appropriate
5843 NT error code. */
5845 if (Printer->jobid == -1) {
5846 return map_werror_from_unix(errno);
5849 Printer->document_started=True;
5850 (*jobid) = Printer->jobid;
5852 return WERR_OK;
5855 /****************************************************************
5856 _spoolss_EndDocPrinter
5857 ****************************************************************/
5859 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5860 struct spoolss_EndDocPrinter *r)
5862 POLICY_HND *handle = r->in.handle;
5864 return _spoolss_enddocprinter_internal(p, handle);
5867 /****************************************************************
5868 _spoolss_WritePrinter
5869 ****************************************************************/
5871 WERROR _spoolss_WritePrinter(pipes_struct *p,
5872 struct spoolss_WritePrinter *r)
5874 POLICY_HND *handle = r->in.handle;
5875 uint32 buffer_size = r->in._data_size;
5876 uint8 *buffer = r->in.data.data;
5877 uint32 *buffer_written = &r->in._data_size;
5878 int snum;
5879 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5881 if (!Printer) {
5882 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5883 OUR_HANDLE(handle)));
5884 *r->out.num_written = r->in._data_size;
5885 return WERR_BADFID;
5888 if (!get_printer_snum(p, handle, &snum, NULL))
5889 return WERR_BADFID;
5891 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5892 (SMB_OFF_T)-1, (size_t)buffer_size);
5893 if (*buffer_written == (uint32)-1) {
5894 *r->out.num_written = 0;
5895 if (errno == ENOSPC)
5896 return WERR_NO_SPOOL_SPACE;
5897 else
5898 return WERR_ACCESS_DENIED;
5901 *r->out.num_written = r->in._data_size;
5903 return WERR_OK;
5906 /********************************************************************
5907 * api_spoolss_getprinter
5908 * called from the spoolss dispatcher
5910 ********************************************************************/
5912 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5913 pipes_struct *p)
5915 int snum;
5916 WERROR errcode = WERR_BADFUNC;
5917 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5919 if (!Printer) {
5920 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5921 return WERR_BADFID;
5924 if (!get_printer_snum(p, handle, &snum, NULL))
5925 return WERR_BADFID;
5927 switch (command) {
5928 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5929 if (print_queue_pause(p->server_info, snum, &errcode)) {
5930 errcode = WERR_OK;
5932 break;
5933 case SPOOLSS_PRINTER_CONTROL_RESUME:
5934 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5935 if (print_queue_resume(p->server_info, snum, &errcode)) {
5936 errcode = WERR_OK;
5938 break;
5939 case SPOOLSS_PRINTER_CONTROL_PURGE:
5940 if (print_queue_purge(p->server_info, snum, &errcode)) {
5941 errcode = WERR_OK;
5943 break;
5944 default:
5945 return WERR_UNKNOWN_LEVEL;
5948 return errcode;
5952 /****************************************************************
5953 _spoolss_AbortPrinter
5954 * From MSDN: "Deletes printer's spool file if printer is configured
5955 * for spooling"
5956 ****************************************************************/
5958 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5959 struct spoolss_AbortPrinter *r)
5961 POLICY_HND *handle = r->in.handle;
5962 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5963 int snum;
5964 WERROR errcode = WERR_OK;
5966 if (!Printer) {
5967 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5968 OUR_HANDLE(handle)));
5969 return WERR_BADFID;
5972 if (!get_printer_snum(p, handle, &snum, NULL))
5973 return WERR_BADFID;
5975 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5977 return errcode;
5980 /********************************************************************
5981 * called by spoolss_api_setprinter
5982 * when updating a printer description
5983 ********************************************************************/
5985 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5986 const SPOOL_PRINTER_INFO_LEVEL *info,
5987 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5989 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5990 WERROR result;
5991 int snum;
5993 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5995 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5996 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5997 OUR_HANDLE(handle)));
5999 result = WERR_BADFID;
6000 goto done;
6003 if (!secdesc_ctr) {
6004 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6005 result = WERR_INVALID_PARAM;
6006 goto done;
6009 /* Check the user has permissions to change the security
6010 descriptor. By experimentation with two NT machines, the user
6011 requires Full Access to the printer to change security
6012 information. */
6014 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6015 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6016 result = WERR_ACCESS_DENIED;
6017 goto done;
6020 /* NT seems to like setting the security descriptor even though
6021 nothing may have actually changed. */
6023 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6024 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6025 result = WERR_BADFID;
6026 goto done;
6029 if (DEBUGLEVEL >= 10) {
6030 SEC_ACL *the_acl;
6031 int i;
6033 the_acl = old_secdesc_ctr->sd->dacl;
6034 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6035 PRINTERNAME(snum), the_acl->num_aces));
6037 for (i = 0; i < the_acl->num_aces; i++) {
6038 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6039 &the_acl->aces[i].trustee),
6040 the_acl->aces[i].access_mask));
6043 the_acl = secdesc_ctr->sd->dacl;
6045 if (the_acl) {
6046 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6047 PRINTERNAME(snum), the_acl->num_aces));
6049 for (i = 0; i < the_acl->num_aces; i++) {
6050 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6051 &the_acl->aces[i].trustee),
6052 the_acl->aces[i].access_mask));
6054 } else {
6055 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6059 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6060 if (!new_secdesc_ctr) {
6061 result = WERR_NOMEM;
6062 goto done;
6065 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6066 result = WERR_OK;
6067 goto done;
6070 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6072 done:
6074 return result;
6077 /********************************************************************
6078 Canonicalize printer info from a client
6080 ATTN: It does not matter what we set the servername to hear
6081 since we do the necessary work in get_a_printer() to set it to
6082 the correct value based on what the client sent in the
6083 _spoolss_open_printer_ex().
6084 ********************************************************************/
6086 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6088 fstring printername;
6089 const char *p;
6091 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6092 "portname=%s drivername=%s comment=%s location=%s\n",
6093 info->servername, info->printername, info->sharename,
6094 info->portname, info->drivername, info->comment, info->location));
6096 /* we force some elements to "correct" values */
6097 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6098 fstrcpy(info->sharename, lp_servicename(snum));
6100 /* check to see if we allow printername != sharename */
6102 if ( lp_force_printername(snum) ) {
6103 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6104 global_myname(), info->sharename );
6105 } else {
6107 /* make sure printername is in \\server\printername format */
6109 fstrcpy( printername, info->printername );
6110 p = printername;
6111 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6112 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6113 p++;
6116 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6117 global_myname(), p );
6120 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6121 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6125 return True;
6128 /****************************************************************************
6129 ****************************************************************************/
6131 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6133 char *cmd = lp_addport_cmd();
6134 char *command = NULL;
6135 int ret;
6136 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6137 bool is_print_op = False;
6139 if ( !*cmd ) {
6140 return WERR_ACCESS_DENIED;
6143 command = talloc_asprintf(ctx,
6144 "%s \"%s\" \"%s\"", cmd, portname, uri );
6145 if (!command) {
6146 return WERR_NOMEM;
6149 if ( token )
6150 is_print_op = user_has_privileges( token, &se_printop );
6152 DEBUG(10,("Running [%s]\n", command));
6154 /********* BEGIN SePrintOperatorPrivilege **********/
6156 if ( is_print_op )
6157 become_root();
6159 ret = smbrun(command, NULL);
6161 if ( is_print_op )
6162 unbecome_root();
6164 /********* END SePrintOperatorPrivilege **********/
6166 DEBUGADD(10,("returned [%d]\n", ret));
6168 TALLOC_FREE(command);
6170 if ( ret != 0 ) {
6171 return WERR_ACCESS_DENIED;
6174 return WERR_OK;
6177 /****************************************************************************
6178 ****************************************************************************/
6180 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6182 char *cmd = lp_addprinter_cmd();
6183 char **qlines;
6184 char *command = NULL;
6185 int numlines;
6186 int ret;
6187 int fd;
6188 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6189 bool is_print_op = False;
6190 char *remote_machine = talloc_strdup(ctx, "%m");
6192 if (!remote_machine) {
6193 return false;
6195 remote_machine = talloc_sub_basic(ctx,
6196 current_user_info.smb_name,
6197 current_user_info.domain,
6198 remote_machine);
6199 if (!remote_machine) {
6200 return false;
6203 command = talloc_asprintf(ctx,
6204 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6205 cmd, printer->info_2->printername, printer->info_2->sharename,
6206 printer->info_2->portname, printer->info_2->drivername,
6207 printer->info_2->location, printer->info_2->comment, remote_machine);
6208 if (!command) {
6209 return false;
6212 if ( token )
6213 is_print_op = user_has_privileges( token, &se_printop );
6215 DEBUG(10,("Running [%s]\n", command));
6217 /********* BEGIN SePrintOperatorPrivilege **********/
6219 if ( is_print_op )
6220 become_root();
6222 if ( (ret = smbrun(command, &fd)) == 0 ) {
6223 /* Tell everyone we updated smb.conf. */
6224 message_send_all(smbd_messaging_context(),
6225 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6228 if ( is_print_op )
6229 unbecome_root();
6231 /********* END SePrintOperatorPrivilege **********/
6233 DEBUGADD(10,("returned [%d]\n", ret));
6235 TALLOC_FREE(command);
6236 TALLOC_FREE(remote_machine);
6238 if ( ret != 0 ) {
6239 if (fd != -1)
6240 close(fd);
6241 return False;
6244 /* reload our services immediately */
6245 reload_services( False );
6247 numlines = 0;
6248 /* Get lines and convert them back to dos-codepage */
6249 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6250 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6251 close(fd);
6253 /* Set the portname to what the script says the portname should be. */
6254 /* but don't require anything to be return from the script exit a good error code */
6256 if (numlines) {
6257 /* Set the portname to what the script says the portname should be. */
6258 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6259 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6262 TALLOC_FREE(qlines);
6263 return True;
6267 /********************************************************************
6268 * Called by spoolss_api_setprinter
6269 * when updating a printer description.
6270 ********************************************************************/
6272 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6273 const SPOOL_PRINTER_INFO_LEVEL *info,
6274 DEVICEMODE *devmode)
6276 int snum;
6277 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6278 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6279 WERROR result;
6280 UNISTR2 buffer;
6281 fstring asc_buffer;
6283 DEBUG(8,("update_printer\n"));
6285 result = WERR_OK;
6287 if (!Printer) {
6288 result = WERR_BADFID;
6289 goto done;
6292 if (!get_printer_snum(p, handle, &snum, NULL)) {
6293 result = WERR_BADFID;
6294 goto done;
6297 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6298 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6299 result = WERR_BADFID;
6300 goto done;
6303 DEBUGADD(8,("Converting info_2 struct\n"));
6306 * convert_printer_info converts the incoming
6307 * info from the client and overwrites the info
6308 * just read from the tdb in the pointer 'printer'.
6311 if (!convert_printer_info(info, printer, level)) {
6312 result = WERR_NOMEM;
6313 goto done;
6316 if (devmode) {
6317 /* we have a valid devmode
6318 convert it and link it*/
6320 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6321 if (!convert_devicemode(printer->info_2->printername, devmode,
6322 &printer->info_2->devmode)) {
6323 result = WERR_NOMEM;
6324 goto done;
6328 /* Do sanity check on the requested changes for Samba */
6330 if (!check_printer_ok(printer->info_2, snum)) {
6331 result = WERR_INVALID_PARAM;
6332 goto done;
6335 /* FIXME!!! If the driver has changed we really should verify that
6336 it is installed before doing much else --jerry */
6338 /* Check calling user has permission to update printer description */
6340 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6341 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6342 result = WERR_ACCESS_DENIED;
6343 goto done;
6346 /* Call addprinter hook */
6347 /* Check changes to see if this is really needed */
6349 if ( *lp_addprinter_cmd()
6350 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6351 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6352 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6353 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6355 /* add_printer_hook() will call reload_services() */
6357 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6358 printer) ) {
6359 result = WERR_ACCESS_DENIED;
6360 goto done;
6365 * When a *new* driver is bound to a printer, the drivername is used to
6366 * lookup previously saved driver initialization info, which is then
6367 * bound to the printer, simulating what happens in the Windows arch.
6369 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6371 if (!set_driver_init(printer, 2))
6373 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6374 printer->info_2->drivername));
6377 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6378 printer->info_2->drivername));
6380 notify_printer_driver(snum, printer->info_2->drivername);
6384 * flag which changes actually occured. This is a small subset of
6385 * all the possible changes. We also have to update things in the
6386 * DsSpooler key.
6389 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6390 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6391 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6392 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6394 notify_printer_comment(snum, printer->info_2->comment);
6397 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6398 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6399 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6400 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6402 notify_printer_sharename(snum, printer->info_2->sharename);
6405 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6406 char *pname;
6408 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6409 pname++;
6410 else
6411 pname = printer->info_2->printername;
6414 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6415 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6416 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6418 notify_printer_printername( snum, pname );
6421 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6422 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6423 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6424 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6426 notify_printer_port(snum, printer->info_2->portname);
6429 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6430 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6431 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6432 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6434 notify_printer_location(snum, printer->info_2->location);
6437 /* here we need to update some more DsSpooler keys */
6438 /* uNCName, serverName, shortServerName */
6440 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6441 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6442 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6443 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6444 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6446 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6447 global_myname(), printer->info_2->sharename );
6448 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6449 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6450 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6452 /* Update printer info */
6453 result = mod_a_printer(printer, 2);
6455 done:
6456 free_a_printer(&printer, 2);
6457 free_a_printer(&old_printer, 2);
6460 return result;
6463 /****************************************************************************
6464 ****************************************************************************/
6465 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6466 const SPOOL_PRINTER_INFO_LEVEL *info)
6468 #ifdef HAVE_ADS
6469 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6470 int snum;
6471 Printer_entry *Printer;
6473 if ( lp_security() != SEC_ADS ) {
6474 return WERR_UNKNOWN_LEVEL;
6477 Printer = find_printer_index_by_hnd(p, handle);
6479 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6481 if (!Printer)
6482 return WERR_BADFID;
6484 if (!get_printer_snum(p, handle, &snum, NULL))
6485 return WERR_BADFID;
6487 nt_printer_publish(Printer, snum, info7->action);
6489 return WERR_OK;
6490 #else
6491 return WERR_UNKNOWN_LEVEL;
6492 #endif
6494 /****************************************************************************
6495 ****************************************************************************/
6497 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6499 POLICY_HND *handle = &q_u->handle;
6500 uint32 level = q_u->level;
6501 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6502 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6503 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6504 uint32 command = q_u->command;
6505 WERROR result;
6507 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6509 if (!Printer) {
6510 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6511 return WERR_BADFID;
6514 /* check the level */
6515 switch (level) {
6516 case 0:
6517 return control_printer(handle, command, p);
6518 case 2:
6519 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6520 if (!W_ERROR_IS_OK(result))
6521 return result;
6522 if (secdesc_ctr)
6523 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6524 return result;
6525 case 3:
6526 return update_printer_sec(handle, level, info, p,
6527 secdesc_ctr);
6528 case 7:
6529 return publish_or_unpublish_printer(p, handle, info);
6530 default:
6531 return WERR_UNKNOWN_LEVEL;
6535 /****************************************************************
6536 _spoolss_FindClosePrinterNotify
6537 ****************************************************************/
6539 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6540 struct spoolss_FindClosePrinterNotify *r)
6542 POLICY_HND *handle = r->in.handle;
6543 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6545 if (!Printer) {
6546 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6547 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6548 return WERR_BADFID;
6551 if (Printer->notify.client_connected==True) {
6552 int snum = -1;
6554 if ( Printer->printer_type == SPLHND_SERVER)
6555 snum = -1;
6556 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6557 !get_printer_snum(p, handle, &snum, NULL) )
6558 return WERR_BADFID;
6560 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6563 Printer->notify.flags=0;
6564 Printer->notify.options=0;
6565 Printer->notify.localmachine[0]='\0';
6566 Printer->notify.printerlocal=0;
6567 if (Printer->notify.option)
6568 free_spool_notify_option(&Printer->notify.option);
6569 Printer->notify.client_connected=False;
6571 return WERR_OK;
6574 /****************************************************************
6575 _spoolss_AddJob
6576 ****************************************************************/
6578 WERROR _spoolss_AddJob(pipes_struct *p,
6579 struct spoolss_AddJob *r)
6581 if (!r->in.buffer && (r->in.offered != 0)) {
6582 return WERR_INVALID_PARAM;
6585 /* this is what a NT server returns for AddJob. AddJob must fail on
6586 * non-local printers */
6588 return WERR_INVALID_PARAM;
6591 /****************************************************************************
6592 ****************************************************************************/
6594 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6595 int position, int snum,
6596 const NT_PRINTER_INFO_LEVEL *ntprinter)
6598 struct tm *t;
6600 t=gmtime(&queue->time);
6602 job_info->jobid=queue->job;
6603 init_unistr(&job_info->printername, lp_servicename(snum));
6604 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6605 init_unistr(&job_info->username, queue->fs_user);
6606 init_unistr(&job_info->document, queue->fs_file);
6607 init_unistr(&job_info->datatype, "RAW");
6608 init_unistr(&job_info->text_status, "");
6609 job_info->status=nt_printj_status(queue->status);
6610 job_info->priority=queue->priority;
6611 job_info->position=position;
6612 job_info->totalpages=queue->page_count;
6613 job_info->pagesprinted=0;
6615 make_systemtime(&job_info->submitted, t);
6618 /****************************************************************************
6619 ****************************************************************************/
6621 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6622 int position, int snum,
6623 const NT_PRINTER_INFO_LEVEL *ntprinter,
6624 DEVICEMODE *devmode)
6626 struct tm *t;
6628 t=gmtime(&queue->time);
6630 job_info->jobid=queue->job;
6632 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6634 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6635 init_unistr(&job_info->username, queue->fs_user);
6636 init_unistr(&job_info->document, queue->fs_file);
6637 init_unistr(&job_info->notifyname, queue->fs_user);
6638 init_unistr(&job_info->datatype, "RAW");
6639 init_unistr(&job_info->printprocessor, "winprint");
6640 init_unistr(&job_info->parameters, "");
6641 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6642 init_unistr(&job_info->text_status, "");
6644 /* and here the security descriptor */
6646 job_info->status=nt_printj_status(queue->status);
6647 job_info->priority=queue->priority;
6648 job_info->position=position;
6649 job_info->starttime=0;
6650 job_info->untiltime=0;
6651 job_info->totalpages=queue->page_count;
6652 job_info->size=queue->size;
6653 make_systemtime(&(job_info->submitted), t);
6654 job_info->timeelapsed=0;
6655 job_info->pagesprinted=0;
6657 job_info->devmode = devmode;
6659 return (True);
6662 /****************************************************************************
6663 Enumjobs at level 1.
6664 ****************************************************************************/
6666 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6667 const NT_PRINTER_INFO_LEVEL *ntprinter,
6668 RPC_BUFFER *buffer, uint32 offered,
6669 uint32 *needed, uint32 *returned)
6671 JOB_INFO_1 *info;
6672 int i;
6673 WERROR result = WERR_OK;
6675 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6676 if (info==NULL) {
6677 *returned=0;
6678 return WERR_NOMEM;
6681 for (i=0; i<*returned; i++)
6682 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6684 /* check the required size. */
6685 for (i=0; i<*returned; i++)
6686 (*needed) += spoolss_size_job_info_1(&info[i]);
6688 if (*needed > offered) {
6689 result = WERR_INSUFFICIENT_BUFFER;
6690 goto out;
6693 if (!rpcbuf_alloc_size(buffer, *needed)) {
6694 result = WERR_NOMEM;
6695 goto out;
6698 /* fill the buffer with the structures */
6699 for (i=0; i<*returned; i++)
6700 smb_io_job_info_1("", buffer, &info[i], 0);
6702 out:
6703 /* clear memory */
6704 SAFE_FREE(info);
6706 if ( !W_ERROR_IS_OK(result) )
6707 *returned = 0;
6709 return result;
6712 /****************************************************************************
6713 Enumjobs at level 2.
6714 ****************************************************************************/
6716 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6717 const NT_PRINTER_INFO_LEVEL *ntprinter,
6718 RPC_BUFFER *buffer, uint32 offered,
6719 uint32 *needed, uint32 *returned)
6721 JOB_INFO_2 *info = NULL;
6722 int i;
6723 WERROR result = WERR_OK;
6724 DEVICEMODE *devmode = NULL;
6726 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6727 *returned=0;
6728 return WERR_NOMEM;
6731 /* this should not be a failure condition if the devmode is NULL */
6733 devmode = construct_dev_mode(lp_const_servicename(snum));
6735 for (i=0; i<*returned; i++)
6736 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6738 /* check the required size. */
6739 for (i=0; i<*returned; i++)
6740 (*needed) += spoolss_size_job_info_2(&info[i]);
6742 if (*needed > offered) {
6743 result = WERR_INSUFFICIENT_BUFFER;
6744 goto out;
6747 if (!rpcbuf_alloc_size(buffer, *needed)) {
6748 result = WERR_NOMEM;
6749 goto out;
6752 /* fill the buffer with the structures */
6753 for (i=0; i<*returned; i++)
6754 smb_io_job_info_2("", buffer, &info[i], 0);
6756 out:
6757 free_devmode(devmode);
6758 SAFE_FREE(info);
6760 if ( !W_ERROR_IS_OK(result) )
6761 *returned = 0;
6763 return result;
6767 /****************************************************************************
6768 Enumjobs.
6769 ****************************************************************************/
6771 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6773 POLICY_HND *handle = &q_u->handle;
6774 uint32 level = q_u->level;
6775 RPC_BUFFER *buffer = NULL;
6776 uint32 offered = q_u->offered;
6777 uint32 *needed = &r_u->needed;
6778 uint32 *returned = &r_u->returned;
6779 WERROR wret;
6780 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6781 int snum;
6782 print_status_struct prt_status;
6783 print_queue_struct *queue=NULL;
6785 /* that's an [in out] buffer */
6787 if (!q_u->buffer && (offered!=0)) {
6788 return WERR_INVALID_PARAM;
6791 rpcbuf_move(q_u->buffer, &r_u->buffer);
6792 buffer = r_u->buffer;
6794 DEBUG(4,("_spoolss_enumjobs\n"));
6796 *needed=0;
6797 *returned=0;
6799 /* lookup the printer snum and tdb entry */
6801 if (!get_printer_snum(p, handle, &snum, NULL))
6802 return WERR_BADFID;
6804 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6805 if ( !W_ERROR_IS_OK(wret) )
6806 return wret;
6808 *returned = print_queue_status(snum, &queue, &prt_status);
6809 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6811 if (*returned == 0) {
6812 SAFE_FREE(queue);
6813 free_a_printer(&ntprinter, 2);
6814 return WERR_OK;
6817 switch (level) {
6818 case 1:
6819 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6820 break;
6821 case 2:
6822 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6823 break;
6824 default:
6825 *returned=0;
6826 wret = WERR_UNKNOWN_LEVEL;
6827 break;
6830 SAFE_FREE(queue);
6831 free_a_printer( &ntprinter, 2 );
6832 return wret;
6835 /****************************************************************
6836 _spoolss_ScheduleJob
6837 ****************************************************************/
6839 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6840 struct spoolss_ScheduleJob *r)
6842 return WERR_OK;
6845 /****************************************************************
6846 _spoolss_SetJob
6847 ****************************************************************/
6849 WERROR _spoolss_SetJob(pipes_struct *p,
6850 struct spoolss_SetJob *r)
6852 POLICY_HND *handle = r->in.handle;
6853 uint32 jobid = r->in.job_id;
6854 uint32 command = r->in.command;
6856 int snum;
6857 WERROR errcode = WERR_BADFUNC;
6859 if (!get_printer_snum(p, handle, &snum, NULL)) {
6860 return WERR_BADFID;
6863 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6864 return WERR_INVALID_PRINTER_NAME;
6867 switch (command) {
6868 case SPOOLSS_JOB_CONTROL_CANCEL:
6869 case SPOOLSS_JOB_CONTROL_DELETE:
6870 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6871 errcode = WERR_OK;
6873 break;
6874 case SPOOLSS_JOB_CONTROL_PAUSE:
6875 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6876 errcode = WERR_OK;
6878 break;
6879 case SPOOLSS_JOB_CONTROL_RESTART:
6880 case SPOOLSS_JOB_CONTROL_RESUME:
6881 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6882 errcode = WERR_OK;
6884 break;
6885 default:
6886 return WERR_UNKNOWN_LEVEL;
6889 return errcode;
6892 /****************************************************************************
6893 Enumerates all printer drivers at level 1.
6894 ****************************************************************************/
6896 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6898 int i;
6899 int ndrivers;
6900 uint32 version;
6901 fstring *list = NULL;
6902 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6903 DRIVER_INFO_1 *driver_info_1=NULL;
6904 WERROR result = WERR_OK;
6906 *returned=0;
6908 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6909 list=NULL;
6910 ndrivers=get_ntdrivers(&list, architecture, version);
6911 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6913 if(ndrivers == -1) {
6914 SAFE_FREE(driver_info_1);
6915 return WERR_NOMEM;
6918 if(ndrivers != 0) {
6919 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6920 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6921 SAFE_FREE(list);
6922 return WERR_NOMEM;
6926 for (i=0; i<ndrivers; i++) {
6927 WERROR status;
6928 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6929 ZERO_STRUCT(driver);
6930 status = get_a_printer_driver(&driver, 3, list[i],
6931 architecture, version);
6932 if (!W_ERROR_IS_OK(status)) {
6933 SAFE_FREE(list);
6934 SAFE_FREE(driver_info_1);
6935 return status;
6937 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6938 free_a_printer_driver(driver, 3);
6941 *returned+=ndrivers;
6942 SAFE_FREE(list);
6945 /* check the required size. */
6946 for (i=0; i<*returned; i++) {
6947 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6948 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6951 if (*needed > offered) {
6952 result = WERR_INSUFFICIENT_BUFFER;
6953 goto out;
6956 if (!rpcbuf_alloc_size(buffer, *needed)) {
6957 result = WERR_NOMEM;
6958 goto out;
6961 /* fill the buffer with the driver structures */
6962 for (i=0; i<*returned; i++) {
6963 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6964 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6967 out:
6968 SAFE_FREE(driver_info_1);
6970 if ( !W_ERROR_IS_OK(result) )
6971 *returned = 0;
6973 return result;
6976 /****************************************************************************
6977 Enumerates all printer drivers at level 2.
6978 ****************************************************************************/
6980 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6982 int i;
6983 int ndrivers;
6984 uint32 version;
6985 fstring *list = NULL;
6986 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6987 DRIVER_INFO_2 *driver_info_2=NULL;
6988 WERROR result = WERR_OK;
6990 *returned=0;
6992 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6993 list=NULL;
6994 ndrivers=get_ntdrivers(&list, architecture, version);
6995 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6997 if(ndrivers == -1) {
6998 SAFE_FREE(driver_info_2);
6999 return WERR_NOMEM;
7002 if(ndrivers != 0) {
7003 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7004 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7005 SAFE_FREE(list);
7006 return WERR_NOMEM;
7010 for (i=0; i<ndrivers; i++) {
7011 WERROR status;
7013 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7014 ZERO_STRUCT(driver);
7015 status = get_a_printer_driver(&driver, 3, list[i],
7016 architecture, version);
7017 if (!W_ERROR_IS_OK(status)) {
7018 SAFE_FREE(list);
7019 SAFE_FREE(driver_info_2);
7020 return status;
7022 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7023 free_a_printer_driver(driver, 3);
7026 *returned+=ndrivers;
7027 SAFE_FREE(list);
7030 /* check the required size. */
7031 for (i=0; i<*returned; i++) {
7032 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7033 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7036 if (*needed > offered) {
7037 result = WERR_INSUFFICIENT_BUFFER;
7038 goto out;
7041 if (!rpcbuf_alloc_size(buffer, *needed)) {
7042 result = WERR_NOMEM;
7043 goto out;
7046 /* fill the buffer with the form structures */
7047 for (i=0; i<*returned; i++) {
7048 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7049 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7052 out:
7053 SAFE_FREE(driver_info_2);
7055 if ( !W_ERROR_IS_OK(result) )
7056 *returned = 0;
7058 return result;
7061 /****************************************************************************
7062 Enumerates all printer drivers at level 3.
7063 ****************************************************************************/
7065 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7067 int i;
7068 int ndrivers;
7069 uint32 version;
7070 fstring *list = NULL;
7071 DRIVER_INFO_3 *driver_info_3=NULL;
7072 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7073 WERROR result = WERR_OK;
7075 *returned=0;
7077 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7078 list=NULL;
7079 ndrivers=get_ntdrivers(&list, architecture, version);
7080 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7082 if(ndrivers == -1) {
7083 SAFE_FREE(driver_info_3);
7084 return WERR_NOMEM;
7087 if(ndrivers != 0) {
7088 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7089 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7090 SAFE_FREE(list);
7091 return WERR_NOMEM;
7095 for (i=0; i<ndrivers; i++) {
7096 WERROR status;
7098 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7099 ZERO_STRUCT(driver);
7100 status = get_a_printer_driver(&driver, 3, list[i],
7101 architecture, version);
7102 if (!W_ERROR_IS_OK(status)) {
7103 SAFE_FREE(list);
7104 SAFE_FREE(driver_info_3);
7105 return status;
7107 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7108 free_a_printer_driver(driver, 3);
7111 *returned+=ndrivers;
7112 SAFE_FREE(list);
7115 /* check the required size. */
7116 for (i=0; i<*returned; i++) {
7117 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7118 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7121 if (*needed > offered) {
7122 result = WERR_INSUFFICIENT_BUFFER;
7123 goto out;
7126 if (!rpcbuf_alloc_size(buffer, *needed)) {
7127 result = WERR_NOMEM;
7128 goto out;
7131 /* fill the buffer with the driver structures */
7132 for (i=0; i<*returned; i++) {
7133 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7134 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7137 out:
7138 for (i=0; i<*returned; i++) {
7139 SAFE_FREE(driver_info_3[i].dependentfiles);
7142 SAFE_FREE(driver_info_3);
7144 if ( !W_ERROR_IS_OK(result) )
7145 *returned = 0;
7147 return result;
7150 /****************************************************************************
7151 Enumerates all printer drivers.
7152 ****************************************************************************/
7154 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7156 uint32 level = q_u->level;
7157 RPC_BUFFER *buffer = NULL;
7158 uint32 offered = q_u->offered;
7159 uint32 *needed = &r_u->needed;
7160 uint32 *returned = &r_u->returned;
7161 const char *cservername;
7162 fstring servername;
7163 fstring architecture;
7165 /* that's an [in out] buffer */
7167 if (!q_u->buffer && (offered!=0)) {
7168 return WERR_INVALID_PARAM;
7171 rpcbuf_move(q_u->buffer, &r_u->buffer);
7172 buffer = r_u->buffer;
7174 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7176 *needed = 0;
7177 *returned = 0;
7179 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7180 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7182 cservername = canon_servername(servername);
7184 if (!is_myname_or_ipaddr(cservername))
7185 return WERR_UNKNOWN_PRINTER_DRIVER;
7187 switch (level) {
7188 case 1:
7189 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7190 case 2:
7191 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7192 case 3:
7193 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7194 default:
7195 return WERR_UNKNOWN_LEVEL;
7199 /****************************************************************************
7200 ****************************************************************************/
7202 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7204 form->flag=list->flag;
7205 init_unistr(&form->name, list->name);
7206 form->width=list->width;
7207 form->length=list->length;
7208 form->left=list->left;
7209 form->top=list->top;
7210 form->right=list->right;
7211 form->bottom=list->bottom;
7214 /****************************************************************************
7215 ****************************************************************************/
7217 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7218 struct spoolss_FormInfo1 *form,
7219 nt_forms_struct *list)
7221 form->form_name = talloc_strdup(mem_ctx, list->name);
7222 W_ERROR_HAVE_NO_MEMORY(form->form_name);
7224 form->flags = list->flag;
7225 form->size.width = list->width;
7226 form->size.height = list->length;
7227 form->area.left = list->left;
7228 form->area.top = list->top;
7229 form->area.right = list->right;
7230 form->area.bottom = list->bottom;
7232 return WERR_OK;
7235 /****************************************************************************
7236 ****************************************************************************/
7238 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7240 uint32 level = q_u->level;
7241 RPC_BUFFER *buffer = NULL;
7242 uint32 offered = q_u->offered;
7243 uint32 *needed = &r_u->needed;
7244 uint32 *numofforms = &r_u->numofforms;
7245 uint32 numbuiltinforms;
7247 nt_forms_struct *list=NULL;
7248 nt_forms_struct *builtinlist=NULL;
7249 FORM_1 *forms_1;
7250 int buffer_size=0;
7251 int i;
7253 /* that's an [in out] buffer */
7255 if (!q_u->buffer && (offered!=0) ) {
7256 return WERR_INVALID_PARAM;
7259 rpcbuf_move(q_u->buffer, &r_u->buffer);
7260 buffer = r_u->buffer;
7262 DEBUG(4,("_spoolss_enumforms\n"));
7263 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7264 DEBUGADD(5,("Info level [%d]\n", level));
7266 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7267 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7268 *numofforms = get_ntforms(&list);
7269 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7270 *numofforms += numbuiltinforms;
7272 if (*numofforms == 0) {
7273 SAFE_FREE(builtinlist);
7274 SAFE_FREE(list);
7275 return WERR_NO_MORE_ITEMS;
7278 switch (level) {
7279 case 1:
7280 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7281 SAFE_FREE(builtinlist);
7282 SAFE_FREE(list);
7283 *numofforms=0;
7284 return WERR_NOMEM;
7287 /* construct the list of form structures */
7288 for (i=0; i<numbuiltinforms; i++) {
7289 DEBUGADD(6,("Filling form number [%d]\n",i));
7290 fill_form_1(&forms_1[i], &builtinlist[i]);
7293 SAFE_FREE(builtinlist);
7295 for (; i<*numofforms; i++) {
7296 DEBUGADD(6,("Filling form number [%d]\n",i));
7297 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7300 SAFE_FREE(list);
7302 /* check the required size. */
7303 for (i=0; i<numbuiltinforms; i++) {
7304 DEBUGADD(6,("adding form [%d]'s size\n",i));
7305 buffer_size += spoolss_size_form_1(&forms_1[i]);
7307 for (; i<*numofforms; i++) {
7308 DEBUGADD(6,("adding form [%d]'s size\n",i));
7309 buffer_size += spoolss_size_form_1(&forms_1[i]);
7312 *needed=buffer_size;
7314 if (*needed > offered) {
7315 SAFE_FREE(forms_1);
7316 *numofforms=0;
7317 return WERR_INSUFFICIENT_BUFFER;
7320 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7321 SAFE_FREE(forms_1);
7322 *numofforms=0;
7323 return WERR_NOMEM;
7326 /* fill the buffer with the form structures */
7327 for (i=0; i<numbuiltinforms; i++) {
7328 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7329 smb_io_form_1("", buffer, &forms_1[i], 0);
7331 for (; i<*numofforms; i++) {
7332 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7333 smb_io_form_1("", buffer, &forms_1[i], 0);
7336 SAFE_FREE(forms_1);
7338 return WERR_OK;
7340 default:
7341 SAFE_FREE(list);
7342 SAFE_FREE(builtinlist);
7343 return WERR_UNKNOWN_LEVEL;
7347 /****************************************************************
7348 _spoolss_GetForm
7349 ****************************************************************/
7351 WERROR _spoolss_GetForm(pipes_struct *p,
7352 struct spoolss_GetForm *r)
7354 uint32 level = r->in.level;
7355 uint32 offered = r->in.offered;
7356 uint32 *needed = r->out.needed;
7358 nt_forms_struct *list=NULL;
7359 nt_forms_struct builtin_form;
7360 bool foundBuiltin;
7361 union spoolss_FormInfo info;
7362 struct spoolss_FormInfo1 form_1;
7363 int numofforms=0, i=0;
7365 /* that's an [in out] buffer */
7367 if (!r->in.buffer && (offered!=0)) {
7368 return WERR_INVALID_PARAM;
7371 DEBUG(4,("_spoolss_GetForm\n"));
7372 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7373 DEBUGADD(5,("Info level [%d]\n", level));
7375 foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7376 if (!foundBuiltin) {
7377 numofforms = get_ntforms(&list);
7378 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7380 if (numofforms == 0)
7381 return WERR_BADFID;
7384 ZERO_STRUCT(form_1);
7386 switch (level) {
7387 case 1:
7388 if (foundBuiltin) {
7389 fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7390 } else {
7392 /* Check if the requested name is in the list of form structures */
7393 for (i=0; i<numofforms; i++) {
7395 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7396 list[i].name, r->in.form_name));
7398 if (strequal(r->in.form_name, list[i].name)) {
7399 DEBUGADD(6,("Found form %s number [%d]\n",
7400 r->in.form_name, i));
7401 fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7402 break;
7406 SAFE_FREE(list);
7407 if (i == numofforms) {
7408 return WERR_BADFID;
7411 /* check the required size. */
7413 info.info1 = form_1;
7415 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7417 if (*needed > offered) {
7418 r->out.info = NULL;
7419 return WERR_INSUFFICIENT_BUFFER;
7422 r->out.info->info1 = form_1;
7424 /* fill the buffer with the form structures */
7425 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7426 r->in.form_name, i));
7428 return WERR_OK;
7430 default:
7431 SAFE_FREE(list);
7432 return WERR_UNKNOWN_LEVEL;
7436 /****************************************************************************
7437 ****************************************************************************/
7439 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7441 init_unistr(&port->port_name, name);
7444 /****************************************************************************
7445 TODO: This probably needs distinguish between TCP/IP and Local ports
7446 somehow.
7447 ****************************************************************************/
7449 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7451 init_unistr(&port->port_name, name);
7452 init_unistr(&port->monitor_name, "Local Monitor");
7453 init_unistr(&port->description, SPL_LOCAL_PORT );
7454 port->port_type=PORT_TYPE_WRITE;
7455 port->reserved=0x0;
7459 /****************************************************************************
7460 wrapper around the enumer ports command
7461 ****************************************************************************/
7463 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7465 char *cmd = lp_enumports_cmd();
7466 char **qlines = NULL;
7467 char *command = NULL;
7468 int numlines;
7469 int ret;
7470 int fd;
7472 *count = 0;
7473 *lines = NULL;
7475 /* if no hook then just fill in the default port */
7477 if ( !*cmd ) {
7478 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7479 return WERR_NOMEM;
7481 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7482 TALLOC_FREE(qlines);
7483 return WERR_NOMEM;
7485 qlines[1] = NULL;
7486 numlines = 1;
7488 else {
7489 /* we have a valid enumport command */
7491 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7492 if (!command) {
7493 return WERR_NOMEM;
7496 DEBUG(10,("Running [%s]\n", command));
7497 ret = smbrun(command, &fd);
7498 DEBUG(10,("Returned [%d]\n", ret));
7499 TALLOC_FREE(command);
7500 if (ret != 0) {
7501 if (fd != -1) {
7502 close(fd);
7504 return WERR_ACCESS_DENIED;
7507 numlines = 0;
7508 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7509 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7510 close(fd);
7513 *count = numlines;
7514 *lines = qlines;
7516 return WERR_OK;
7519 /****************************************************************************
7520 enumports level 1.
7521 ****************************************************************************/
7523 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7525 PORT_INFO_1 *ports=NULL;
7526 int i=0;
7527 WERROR result = WERR_OK;
7528 char **qlines = NULL;
7529 int numlines = 0;
7531 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7532 if (!W_ERROR_IS_OK(result)) {
7533 TALLOC_FREE(qlines);
7534 return result;
7537 if(numlines) {
7538 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7539 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7540 win_errstr(WERR_NOMEM)));
7541 TALLOC_FREE(qlines);
7542 return WERR_NOMEM;
7545 for (i=0; i<numlines; i++) {
7546 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7547 fill_port_1(&ports[i], qlines[i]);
7550 TALLOC_FREE(qlines);
7552 *returned = numlines;
7554 /* check the required size. */
7555 for (i=0; i<*returned; i++) {
7556 DEBUGADD(6,("adding port [%d]'s size\n", i));
7557 *needed += spoolss_size_port_info_1(&ports[i]);
7560 if (*needed > offered) {
7561 result = WERR_INSUFFICIENT_BUFFER;
7562 goto out;
7565 if (!rpcbuf_alloc_size(buffer, *needed)) {
7566 result = WERR_NOMEM;
7567 goto out;
7570 /* fill the buffer with the ports structures */
7571 for (i=0; i<*returned; i++) {
7572 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7573 smb_io_port_1("", buffer, &ports[i], 0);
7576 out:
7577 SAFE_FREE(ports);
7579 if ( !W_ERROR_IS_OK(result) )
7580 *returned = 0;
7582 return result;
7585 /****************************************************************************
7586 enumports level 2.
7587 ****************************************************************************/
7589 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7591 PORT_INFO_2 *ports=NULL;
7592 int i=0;
7593 WERROR result = WERR_OK;
7594 char **qlines = NULL;
7595 int numlines = 0;
7597 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7598 if ( !W_ERROR_IS_OK(result)) {
7599 TALLOC_FREE(qlines);
7600 return result;
7603 if(numlines) {
7604 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7605 TALLOC_FREE(qlines);
7606 return WERR_NOMEM;
7609 for (i=0; i<numlines; i++) {
7610 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7611 fill_port_2(&(ports[i]), qlines[i]);
7615 TALLOC_FREE(qlines);
7617 *returned = numlines;
7619 /* check the required size. */
7620 for (i=0; i<*returned; i++) {
7621 DEBUGADD(6,("adding port [%d]'s size\n", i));
7622 *needed += spoolss_size_port_info_2(&ports[i]);
7625 if (*needed > offered) {
7626 result = WERR_INSUFFICIENT_BUFFER;
7627 goto out;
7630 if (!rpcbuf_alloc_size(buffer, *needed)) {
7631 result = WERR_NOMEM;
7632 goto out;
7635 /* fill the buffer with the ports structures */
7636 for (i=0; i<*returned; i++) {
7637 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7638 smb_io_port_2("", buffer, &ports[i], 0);
7641 out:
7642 SAFE_FREE(ports);
7644 if ( !W_ERROR_IS_OK(result) )
7645 *returned = 0;
7647 return result;
7650 /****************************************************************************
7651 enumports.
7652 ****************************************************************************/
7654 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7656 uint32 level = q_u->level;
7657 RPC_BUFFER *buffer = NULL;
7658 uint32 offered = q_u->offered;
7659 uint32 *needed = &r_u->needed;
7660 uint32 *returned = &r_u->returned;
7662 /* that's an [in out] buffer */
7664 if (!q_u->buffer && (offered!=0)) {
7665 return WERR_INVALID_PARAM;
7668 rpcbuf_move(q_u->buffer, &r_u->buffer);
7669 buffer = r_u->buffer;
7671 DEBUG(4,("_spoolss_enumports\n"));
7673 *returned=0;
7674 *needed=0;
7676 switch (level) {
7677 case 1:
7678 return enumports_level_1(buffer, offered, needed, returned);
7679 case 2:
7680 return enumports_level_2(buffer, offered, needed, returned);
7681 default:
7682 return WERR_UNKNOWN_LEVEL;
7686 /****************************************************************************
7687 ****************************************************************************/
7689 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7690 const SPOOL_PRINTER_INFO_LEVEL *info,
7691 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7692 uint32 user_switch, const SPOOL_USER_CTR *user,
7693 POLICY_HND *handle)
7695 NT_PRINTER_INFO_LEVEL *printer = NULL;
7696 fstring name;
7697 int snum;
7698 WERROR err = WERR_OK;
7700 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7701 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7702 return WERR_NOMEM;
7705 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7706 if (!convert_printer_info(info, printer, 2)) {
7707 free_a_printer(&printer, 2);
7708 return WERR_NOMEM;
7711 /* check to see if the printer already exists */
7713 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7714 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7715 printer->info_2->sharename));
7716 free_a_printer(&printer, 2);
7717 return WERR_PRINTER_ALREADY_EXISTS;
7720 /* FIXME!!! smbd should check to see if the driver is installed before
7721 trying to add a printer like this --jerry */
7723 if (*lp_addprinter_cmd() ) {
7724 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7725 printer) ) {
7726 free_a_printer(&printer,2);
7727 return WERR_ACCESS_DENIED;
7729 } else {
7730 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7731 "smb.conf parameter \"addprinter command\" is defined. This"
7732 "parameter must exist for this call to succeed\n",
7733 printer->info_2->sharename ));
7736 /* use our primary netbios name since get_a_printer() will convert
7737 it to what the client expects on a case by case basis */
7739 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7740 printer->info_2->sharename);
7743 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7744 free_a_printer(&printer,2);
7745 return WERR_ACCESS_DENIED;
7748 /* you must be a printer admin to add a new printer */
7749 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7750 free_a_printer(&printer,2);
7751 return WERR_ACCESS_DENIED;
7755 * Do sanity check on the requested changes for Samba.
7758 if (!check_printer_ok(printer->info_2, snum)) {
7759 free_a_printer(&printer,2);
7760 return WERR_INVALID_PARAM;
7764 * When a printer is created, the drivername bound to the printer is used
7765 * to lookup previously saved driver initialization info, which is then
7766 * bound to the new printer, simulating what happens in the Windows arch.
7769 if (!devmode)
7771 set_driver_init(printer, 2);
7773 else
7775 /* A valid devmode was included, convert and link it
7777 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7779 if (!convert_devicemode(printer->info_2->printername, devmode,
7780 &printer->info_2->devmode))
7781 return WERR_NOMEM;
7784 /* write the ASCII on disk */
7785 err = mod_a_printer(printer, 2);
7786 if (!W_ERROR_IS_OK(err)) {
7787 free_a_printer(&printer,2);
7788 return err;
7791 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7792 /* Handle open failed - remove addition. */
7793 del_a_printer(printer->info_2->sharename);
7794 free_a_printer(&printer,2);
7795 return WERR_ACCESS_DENIED;
7798 update_c_setprinter(False);
7799 free_a_printer(&printer,2);
7801 return WERR_OK;
7804 /****************************************************************************
7805 ****************************************************************************/
7807 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7809 UNISTR2 *uni_srv_name = q_u->server_name;
7810 uint32 level = q_u->level;
7811 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7812 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7813 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7814 uint32 user_switch = q_u->user_switch;
7815 SPOOL_USER_CTR *user = &q_u->user_ctr;
7816 POLICY_HND *handle = &r_u->handle;
7818 switch (level) {
7819 case 1:
7820 /* we don't handle yet */
7821 /* but I know what to do ... */
7822 return WERR_UNKNOWN_LEVEL;
7823 case 2:
7824 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7825 devmode, sdb,
7826 user_switch, user, handle);
7827 default:
7828 return WERR_UNKNOWN_LEVEL;
7832 /****************************************************************************
7833 ****************************************************************************/
7835 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7837 uint32 level = q_u->level;
7838 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7839 WERROR err = WERR_OK;
7840 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7841 fstring driver_name;
7842 uint32 version;
7844 ZERO_STRUCT(driver);
7846 if (!convert_printer_driver_info(info, &driver, level)) {
7847 err = WERR_NOMEM;
7848 goto done;
7851 DEBUG(5,("Cleaning driver's information\n"));
7852 err = clean_up_driver_struct(p, driver, level);
7853 if (!W_ERROR_IS_OK(err))
7854 goto done;
7856 DEBUG(5,("Moving driver to final destination\n"));
7857 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7858 &err)) ) {
7859 goto done;
7862 if (add_a_printer_driver(driver, level)!=0) {
7863 err = WERR_ACCESS_DENIED;
7864 goto done;
7867 switch(level) {
7868 case 3:
7869 fstrcpy(driver_name,
7870 driver.info_3->name ? driver.info_3->name : "");
7871 break;
7872 case 6:
7873 fstrcpy(driver_name,
7874 driver.info_6->name ? driver.info_6->name : "");
7875 break;
7879 * I think this is where he DrvUpgradePrinter() hook would be
7880 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7881 * server. Right now, we just need to send ourselves a message
7882 * to update each printer bound to this driver. --jerry
7885 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7886 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7887 driver_name));
7891 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7892 * decide if the driver init data should be deleted. The rules are:
7893 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7894 * 2) delete init data only if there is no 2k/Xp driver
7895 * 3) always delete init data
7896 * The generalized rule is always use init data from the highest order driver.
7897 * It is necessary to follow the driver install by an initialization step to
7898 * finish off this process.
7900 if (level == 3)
7901 version = driver.info_3->cversion;
7902 else if (level == 6)
7903 version = driver.info_6->version;
7904 else
7905 version = -1;
7906 switch (version) {
7908 * 9x printer driver - never delete init data
7910 case 0:
7911 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7912 driver_name));
7913 break;
7916 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7917 * there is no 2k/Xp driver init data for this driver name.
7919 case 2:
7921 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7923 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7925 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7927 if (!del_driver_init(driver_name))
7928 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7929 } else {
7931 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7933 free_a_printer_driver(driver1,3);
7934 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7935 driver_name));
7938 break;
7941 * 2k or Xp printer driver - always delete init data
7943 case 3:
7944 if (!del_driver_init(driver_name))
7945 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7946 break;
7948 default:
7949 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7950 break;
7954 done:
7955 free_a_printer_driver(driver, level);
7956 return err;
7959 /********************************************************************
7960 * spoolss_addprinterdriverex
7961 ********************************************************************/
7963 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7965 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7966 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7969 * we only support the semantics of AddPrinterDriver()
7970 * i.e. only copy files that are newer than existing ones
7973 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7974 return WERR_ACCESS_DENIED;
7976 ZERO_STRUCT(q_u_local);
7977 ZERO_STRUCT(r_u_local);
7979 /* just pass the information off to _spoolss_addprinterdriver() */
7980 q_u_local.server_name_ptr = q_u->server_name_ptr;
7981 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7982 q_u_local.level = q_u->level;
7983 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7985 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7988 /****************************************************************************
7989 ****************************************************************************/
7991 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7993 init_unistr(&info->name, name);
7996 /****************************************************************************
7997 ****************************************************************************/
7999 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
8001 char *path = NULL;
8002 char *long_archi = NULL;
8003 char *servername = NULL;
8004 const char *pservername = NULL;
8005 const char *short_archi;
8006 DRIVER_DIRECTORY_1 *info=NULL;
8007 WERROR result = WERR_OK;
8008 TALLOC_CTX *ctx = talloc_tos();
8010 servername = unistr2_to_ascii_talloc(ctx, name);
8011 if (!servername) {
8012 return WERR_NOMEM;
8014 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
8015 if (!long_archi) {
8016 return WERR_NOMEM;
8019 pservername = canon_servername(servername);
8021 if ( !is_myname_or_ipaddr(pservername))
8022 return WERR_INVALID_PARAM;
8024 if (!(short_archi = get_short_archi(long_archi)))
8025 return WERR_INVALID_ENVIRONMENT;
8027 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8028 return WERR_NOMEM;
8030 path = talloc_asprintf(ctx,
8031 "\\\\%s\\print$\\%s", pservername, short_archi);
8032 if (!path) {
8033 result = WERR_NOMEM;
8034 goto out;
8037 DEBUG(4,("printer driver directory: [%s]\n", path));
8039 fill_driverdir_1(info, path);
8041 *needed += spoolss_size_driverdir_info_1(info);
8043 if (*needed > offered) {
8044 result = WERR_INSUFFICIENT_BUFFER;
8045 goto out;
8048 if (!rpcbuf_alloc_size(buffer, *needed)) {
8049 result = WERR_NOMEM;
8050 goto out;
8053 smb_io_driverdir_1("", buffer, info, 0);
8055 out:
8056 SAFE_FREE(info);
8058 return result;
8061 /****************************************************************************
8062 ****************************************************************************/
8064 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8066 UNISTR2 *name = &q_u->name;
8067 UNISTR2 *uni_environment = &q_u->environment;
8068 uint32 level = q_u->level;
8069 RPC_BUFFER *buffer = NULL;
8070 uint32 offered = q_u->offered;
8071 uint32 *needed = &r_u->needed;
8073 /* that's an [in out] buffer */
8075 if (!q_u->buffer && (offered!=0)) {
8076 return WERR_INVALID_PARAM;
8079 rpcbuf_move(q_u->buffer, &r_u->buffer);
8080 buffer = r_u->buffer;
8082 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8084 *needed=0;
8086 switch(level) {
8087 case 1:
8088 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8089 default:
8090 return WERR_UNKNOWN_LEVEL;
8094 /****************************************************************************
8095 ****************************************************************************/
8097 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8099 POLICY_HND *handle = &q_u->handle;
8100 uint32 idx = q_u->index;
8101 uint32 in_value_len = q_u->valuesize;
8102 uint32 in_data_len = q_u->datasize;
8103 uint32 *out_max_value_len = &r_u->valuesize;
8104 uint16 **out_value = &r_u->value;
8105 uint32 *out_value_len = &r_u->realvaluesize;
8106 uint32 *out_type = &r_u->type;
8107 uint32 *out_max_data_len = &r_u->datasize;
8108 uint8 **data_out = &r_u->data;
8109 uint32 *out_data_len = &r_u->realdatasize;
8111 NT_PRINTER_INFO_LEVEL *printer = NULL;
8113 uint32 biggest_valuesize;
8114 uint32 biggest_datasize;
8115 uint32 data_len;
8116 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8117 int snum;
8118 WERROR result;
8119 REGISTRY_VALUE *val = NULL;
8120 NT_PRINTER_DATA *p_data;
8121 int i, key_index, num_values;
8122 int name_length;
8124 *out_type = 0;
8126 *out_max_data_len = 0;
8127 *data_out = NULL;
8128 *out_data_len = 0;
8130 DEBUG(5,("spoolss_enumprinterdata\n"));
8132 if (!Printer) {
8133 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8134 return WERR_BADFID;
8137 if (!get_printer_snum(p,handle, &snum, NULL))
8138 return WERR_BADFID;
8140 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8141 if (!W_ERROR_IS_OK(result))
8142 return result;
8144 p_data = printer->info_2->data;
8145 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8147 result = WERR_OK;
8150 * The NT machine wants to know the biggest size of value and data
8152 * cf: MSDN EnumPrinterData remark section
8155 if ( !in_value_len && !in_data_len && (key_index != -1) )
8157 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8159 biggest_valuesize = 0;
8160 biggest_datasize = 0;
8162 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8164 for ( i=0; i<num_values; i++ )
8166 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8168 name_length = strlen(val->valuename);
8169 if ( strlen(val->valuename) > biggest_valuesize )
8170 biggest_valuesize = name_length;
8172 if ( val->size > biggest_datasize )
8173 biggest_datasize = val->size;
8175 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8176 biggest_datasize));
8179 /* the value is an UNICODE string but real_value_size is the length
8180 in bytes including the trailing 0 */
8182 *out_value_len = 2 * (1+biggest_valuesize);
8183 *out_data_len = biggest_datasize;
8185 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8187 goto done;
8191 * the value len is wrong in NT sp3
8192 * that's the number of bytes not the number of unicode chars
8195 if ( key_index != -1 )
8196 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8198 if ( !val )
8201 /* out_value should default to "" or else NT4 has
8202 problems unmarshalling the response */
8204 *out_max_value_len=(in_value_len/sizeof(uint16));
8206 if (in_value_len) {
8207 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8209 result = WERR_NOMEM;
8210 goto done;
8212 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8213 } else {
8214 *out_value=NULL;
8215 *out_value_len = 0;
8218 /* the data is counted in bytes */
8220 *out_max_data_len = in_data_len;
8221 *out_data_len = in_data_len;
8223 /* only allocate when given a non-zero data_len */
8225 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8227 result = WERR_NOMEM;
8228 goto done;
8231 result = WERR_NO_MORE_ITEMS;
8233 else
8236 * the value is:
8237 * - counted in bytes in the request
8238 * - counted in UNICODE chars in the max reply
8239 * - counted in bytes in the real size
8241 * take a pause *before* coding not *during* coding
8244 /* name */
8245 *out_max_value_len=(in_value_len/sizeof(uint16));
8246 if (in_value_len) {
8247 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8249 result = WERR_NOMEM;
8250 goto done;
8253 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8254 } else {
8255 *out_value = NULL;
8256 *out_value_len = 0;
8259 /* type */
8261 *out_type = regval_type( val );
8263 /* data - counted in bytes */
8265 *out_max_data_len = in_data_len;
8266 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8268 result = WERR_NOMEM;
8269 goto done;
8271 data_len = regval_size(val);
8272 if ( *data_out && data_len )
8273 memcpy( *data_out, regval_data_p(val), data_len );
8274 *out_data_len = data_len;
8277 done:
8278 free_a_printer(&printer, 2);
8279 return result;
8282 /****************************************************************************
8283 ****************************************************************************/
8285 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8287 POLICY_HND *handle = &q_u->handle;
8288 UNISTR2 *value = &q_u->value;
8289 uint32 type = q_u->type;
8290 uint8 *data = q_u->data;
8291 uint32 real_len = q_u->real_len;
8293 NT_PRINTER_INFO_LEVEL *printer = NULL;
8294 int snum=0;
8295 WERROR status = WERR_OK;
8296 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8297 fstring valuename;
8299 DEBUG(5,("spoolss_setprinterdata\n"));
8301 if (!Printer) {
8302 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8303 return WERR_BADFID;
8306 if ( Printer->printer_type == SPLHND_SERVER ) {
8307 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8308 return WERR_INVALID_PARAM;
8311 if (!get_printer_snum(p,handle, &snum, NULL))
8312 return WERR_BADFID;
8315 * Access check : NT returns "access denied" if you make a
8316 * SetPrinterData call without the necessary privildge.
8317 * we were originally returning OK if nothing changed
8318 * which made Win2k issue **a lot** of SetPrinterData
8319 * when connecting to a printer --jerry
8322 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8324 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8325 status = WERR_ACCESS_DENIED;
8326 goto done;
8329 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8330 if (!W_ERROR_IS_OK(status))
8331 return status;
8333 unistr2_to_ascii(valuename, value, sizeof(valuename));
8336 * When client side code sets a magic printer data key, detect it and save
8337 * the current printer data and the magic key's data (its the DEVMODE) for
8338 * future printer/driver initializations.
8340 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8342 /* Set devmode and printer initialization info */
8343 status = save_driver_init( printer, 2, data, real_len );
8345 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8347 else
8349 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8350 type, data, real_len );
8351 if ( W_ERROR_IS_OK(status) )
8352 status = mod_a_printer(printer, 2);
8355 done:
8356 free_a_printer(&printer, 2);
8358 return status;
8361 /****************************************************************************
8362 ****************************************************************************/
8364 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8366 POLICY_HND *handle = &q_u->handle;
8367 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8368 int snum;
8370 DEBUG(5,("_spoolss_resetprinter\n"));
8373 * All we do is to check to see if the handle and queue is valid.
8374 * This call really doesn't mean anything to us because we only
8375 * support RAW printing. --jerry
8378 if (!Printer) {
8379 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8380 return WERR_BADFID;
8383 if (!get_printer_snum(p,handle, &snum, NULL))
8384 return WERR_BADFID;
8387 /* blindly return success */
8388 return WERR_OK;
8391 /****************************************************************
8392 _spoolss_DeletePrinterData
8393 ****************************************************************/
8395 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8396 struct spoolss_DeletePrinterData *r)
8398 POLICY_HND *handle = r->in.handle;
8399 NT_PRINTER_INFO_LEVEL *printer = NULL;
8400 int snum=0;
8401 WERROR status = WERR_OK;
8402 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8404 DEBUG(5,("_spoolss_DeletePrinterData\n"));
8406 if (!Printer) {
8407 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8408 OUR_HANDLE(handle)));
8409 return WERR_BADFID;
8412 if (!get_printer_snum(p, handle, &snum, NULL))
8413 return WERR_BADFID;
8415 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8416 DEBUG(3, ("_spoolss_DeletePrinterData: "
8417 "printer properties change denied by handle\n"));
8418 return WERR_ACCESS_DENIED;
8421 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8422 if (!W_ERROR_IS_OK(status))
8423 return status;
8425 if (!r->in.value_name) {
8426 free_a_printer(&printer, 2);
8427 return WERR_NOMEM;
8430 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8431 r->in.value_name );
8433 if ( W_ERROR_IS_OK(status) )
8434 mod_a_printer( printer, 2 );
8436 free_a_printer(&printer, 2);
8438 return status;
8441 /****************************************************************
8442 _spoolss_AddForm
8443 ****************************************************************/
8445 WERROR _spoolss_AddForm(pipes_struct *p,
8446 struct spoolss_AddForm *r)
8448 POLICY_HND *handle = r->in.handle;
8449 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8450 nt_forms_struct tmpForm;
8451 int snum;
8452 WERROR status = WERR_OK;
8453 NT_PRINTER_INFO_LEVEL *printer = NULL;
8455 int count=0;
8456 nt_forms_struct *list=NULL;
8457 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8459 DEBUG(5,("_spoolss_AddForm\n"));
8461 if (!Printer) {
8462 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8463 OUR_HANDLE(handle)));
8464 return WERR_BADFID;
8468 /* forms can be added on printer of on the print server handle */
8470 if ( Printer->printer_type == SPLHND_PRINTER )
8472 if (!get_printer_snum(p,handle, &snum, NULL))
8473 return WERR_BADFID;
8475 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8476 if (!W_ERROR_IS_OK(status))
8477 goto done;
8480 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8481 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8482 status = WERR_ACCESS_DENIED;
8483 goto done;
8486 /* can't add if builtin */
8488 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8489 status = WERR_FILE_EXISTS;
8490 goto done;
8493 count = get_ntforms(&list);
8495 if(!add_a_form(&list, form, &count)) {
8496 status = WERR_NOMEM;
8497 goto done;
8500 write_ntforms(&list, count);
8503 * ChangeID must always be set if this is a printer
8506 if ( Printer->printer_type == SPLHND_PRINTER )
8507 status = mod_a_printer(printer, 2);
8509 done:
8510 if ( printer )
8511 free_a_printer(&printer, 2);
8512 SAFE_FREE(list);
8514 return status;
8517 /****************************************************************
8518 _spoolss_DeleteForm
8519 ****************************************************************/
8521 WERROR _spoolss_DeleteForm(pipes_struct *p,
8522 struct spoolss_DeleteForm *r)
8524 POLICY_HND *handle = r->in.handle;
8525 const char *form_name = r->in.form_name;
8526 nt_forms_struct tmpForm;
8527 int count=0;
8528 nt_forms_struct *list=NULL;
8529 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8530 int snum;
8531 WERROR status = WERR_OK;
8532 NT_PRINTER_INFO_LEVEL *printer = NULL;
8534 DEBUG(5,("_spoolss_DeleteForm\n"));
8536 if (!Printer) {
8537 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8538 OUR_HANDLE(handle)));
8539 return WERR_BADFID;
8542 /* forms can be deleted on printer of on the print server handle */
8544 if ( Printer->printer_type == SPLHND_PRINTER )
8546 if (!get_printer_snum(p,handle, &snum, NULL))
8547 return WERR_BADFID;
8549 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8550 if (!W_ERROR_IS_OK(status))
8551 goto done;
8554 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8555 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8556 status = WERR_ACCESS_DENIED;
8557 goto done;
8560 /* can't delete if builtin */
8562 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8563 status = WERR_INVALID_PARAM;
8564 goto done;
8567 count = get_ntforms(&list);
8569 if ( !delete_a_form(&list, form_name, &count, &status ))
8570 goto done;
8573 * ChangeID must always be set if this is a printer
8576 if ( Printer->printer_type == SPLHND_PRINTER )
8577 status = mod_a_printer(printer, 2);
8579 done:
8580 if ( printer )
8581 free_a_printer(&printer, 2);
8582 SAFE_FREE(list);
8584 return status;
8587 /****************************************************************
8588 _spoolss_SetForm
8589 ****************************************************************/
8591 WERROR _spoolss_SetForm(pipes_struct *p,
8592 struct spoolss_SetForm *r)
8594 POLICY_HND *handle = r->in.handle;
8595 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8596 nt_forms_struct tmpForm;
8597 int snum;
8598 WERROR status = WERR_OK;
8599 NT_PRINTER_INFO_LEVEL *printer = NULL;
8601 int count=0;
8602 nt_forms_struct *list=NULL;
8603 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8605 DEBUG(5,("_spoolss_SetForm\n"));
8607 if (!Printer) {
8608 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8609 OUR_HANDLE(handle)));
8610 return WERR_BADFID;
8613 /* forms can be modified on printer of on the print server handle */
8615 if ( Printer->printer_type == SPLHND_PRINTER )
8617 if (!get_printer_snum(p,handle, &snum, NULL))
8618 return WERR_BADFID;
8620 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8621 if (!W_ERROR_IS_OK(status))
8622 goto done;
8625 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8626 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8627 status = WERR_ACCESS_DENIED;
8628 goto done;
8631 /* can't set if builtin */
8632 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8633 status = WERR_INVALID_PARAM;
8634 goto done;
8637 count = get_ntforms(&list);
8638 update_a_form(&list, form, count);
8639 write_ntforms(&list, count);
8642 * ChangeID must always be set if this is a printer
8645 if ( Printer->printer_type == SPLHND_PRINTER )
8646 status = mod_a_printer(printer, 2);
8649 done:
8650 if ( printer )
8651 free_a_printer(&printer, 2);
8652 SAFE_FREE(list);
8654 return status;
8657 /****************************************************************************
8658 enumprintprocessors level 1.
8659 ****************************************************************************/
8661 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8663 PRINTPROCESSOR_1 *info_1=NULL;
8664 WERROR result = WERR_OK;
8666 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8667 return WERR_NOMEM;
8669 (*returned) = 0x1;
8671 init_unistr(&info_1->name, "winprint");
8673 *needed += spoolss_size_printprocessor_info_1(info_1);
8675 if (*needed > offered) {
8676 result = WERR_INSUFFICIENT_BUFFER;
8677 goto out;
8680 if (!rpcbuf_alloc_size(buffer, *needed)) {
8681 result = WERR_NOMEM;
8682 goto out;
8685 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8687 out:
8688 SAFE_FREE(info_1);
8690 if ( !W_ERROR_IS_OK(result) )
8691 *returned = 0;
8693 return result;
8696 /****************************************************************************
8697 ****************************************************************************/
8699 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8701 uint32 level = q_u->level;
8702 RPC_BUFFER *buffer = NULL;
8703 uint32 offered = q_u->offered;
8704 uint32 *needed = &r_u->needed;
8705 uint32 *returned = &r_u->returned;
8707 /* that's an [in out] buffer */
8709 if (!q_u->buffer && (offered!=0)) {
8710 return WERR_INVALID_PARAM;
8713 rpcbuf_move(q_u->buffer, &r_u->buffer);
8714 buffer = r_u->buffer;
8716 DEBUG(5,("spoolss_enumprintprocessors\n"));
8719 * Enumerate the print processors ...
8721 * Just reply with "winprint", to keep NT happy
8722 * and I can use my nice printer checker.
8725 *returned=0;
8726 *needed=0;
8728 switch (level) {
8729 case 1:
8730 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8731 default:
8732 return WERR_UNKNOWN_LEVEL;
8736 /****************************************************************************
8737 enumprintprocdatatypes level 1.
8738 ****************************************************************************/
8740 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8742 PRINTPROCDATATYPE_1 *info_1=NULL;
8743 WERROR result = WERR_OK;
8745 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8746 return WERR_NOMEM;
8748 (*returned) = 0x1;
8750 init_unistr(&info_1->name, "RAW");
8752 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8754 if (*needed > offered) {
8755 result = WERR_INSUFFICIENT_BUFFER;
8756 goto out;
8759 if (!rpcbuf_alloc_size(buffer, *needed)) {
8760 result = WERR_NOMEM;
8761 goto out;
8764 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8766 out:
8767 SAFE_FREE(info_1);
8769 if ( !W_ERROR_IS_OK(result) )
8770 *returned = 0;
8772 return result;
8775 /****************************************************************************
8776 ****************************************************************************/
8778 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8780 uint32 level = q_u->level;
8781 RPC_BUFFER *buffer = NULL;
8782 uint32 offered = q_u->offered;
8783 uint32 *needed = &r_u->needed;
8784 uint32 *returned = &r_u->returned;
8786 /* that's an [in out] buffer */
8788 if (!q_u->buffer && (offered!=0)) {
8789 return WERR_INVALID_PARAM;
8792 rpcbuf_move(q_u->buffer, &r_u->buffer);
8793 buffer = r_u->buffer;
8795 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8797 *returned=0;
8798 *needed=0;
8800 switch (level) {
8801 case 1:
8802 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8803 default:
8804 return WERR_UNKNOWN_LEVEL;
8808 /****************************************************************************
8809 enumprintmonitors level 1.
8810 ****************************************************************************/
8812 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8814 PRINTMONITOR_1 *info_1;
8815 WERROR result = WERR_OK;
8816 int i;
8818 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8819 return WERR_NOMEM;
8821 *returned = 2;
8823 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8824 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8826 for ( i=0; i<*returned; i++ ) {
8827 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8830 if (*needed > offered) {
8831 result = WERR_INSUFFICIENT_BUFFER;
8832 goto out;
8835 if (!rpcbuf_alloc_size(buffer, *needed)) {
8836 result = WERR_NOMEM;
8837 goto out;
8840 for ( i=0; i<*returned; i++ ) {
8841 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8844 out:
8845 SAFE_FREE(info_1);
8847 if ( !W_ERROR_IS_OK(result) )
8848 *returned = 0;
8850 return result;
8853 /****************************************************************************
8854 enumprintmonitors level 2.
8855 ****************************************************************************/
8857 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8859 PRINTMONITOR_2 *info_2;
8860 WERROR result = WERR_OK;
8861 int i;
8863 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8864 return WERR_NOMEM;
8866 *returned = 2;
8868 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8869 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8870 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8872 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8873 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8874 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8876 for ( i=0; i<*returned; i++ ) {
8877 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8880 if (*needed > offered) {
8881 result = WERR_INSUFFICIENT_BUFFER;
8882 goto out;
8885 if (!rpcbuf_alloc_size(buffer, *needed)) {
8886 result = WERR_NOMEM;
8887 goto out;
8890 for ( i=0; i<*returned; i++ ) {
8891 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8894 out:
8895 SAFE_FREE(info_2);
8897 if ( !W_ERROR_IS_OK(result) )
8898 *returned = 0;
8900 return result;
8903 /****************************************************************************
8904 ****************************************************************************/
8906 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8908 uint32 level = q_u->level;
8909 RPC_BUFFER *buffer = NULL;
8910 uint32 offered = q_u->offered;
8911 uint32 *needed = &r_u->needed;
8912 uint32 *returned = &r_u->returned;
8914 /* that's an [in out] buffer */
8916 if (!q_u->buffer && (offered!=0)) {
8917 return WERR_INVALID_PARAM;
8920 rpcbuf_move(q_u->buffer, &r_u->buffer);
8921 buffer = r_u->buffer;
8923 DEBUG(5,("spoolss_enumprintmonitors\n"));
8926 * Enumerate the print monitors ...
8928 * Just reply with "Local Port", to keep NT happy
8929 * and I can use my nice printer checker.
8932 *returned=0;
8933 *needed=0;
8935 switch (level) {
8936 case 1:
8937 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8938 case 2:
8939 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8940 default:
8941 return WERR_UNKNOWN_LEVEL;
8945 /****************************************************************************
8946 ****************************************************************************/
8948 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8949 NT_PRINTER_INFO_LEVEL *ntprinter,
8950 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8951 uint32 *needed)
8953 int i=0;
8954 bool found=False;
8955 JOB_INFO_1 *info_1=NULL;
8956 WERROR result = WERR_OK;
8958 info_1=SMB_MALLOC_P(JOB_INFO_1);
8960 if (info_1 == NULL) {
8961 return WERR_NOMEM;
8964 for (i=0; i<count && found==False; i++) {
8965 if ((*queue)[i].job==(int)jobid)
8966 found=True;
8969 if (found==False) {
8970 SAFE_FREE(info_1);
8971 /* NT treats not found as bad param... yet another bad choice */
8972 return WERR_INVALID_PARAM;
8975 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8977 *needed += spoolss_size_job_info_1(info_1);
8979 if (*needed > offered) {
8980 result = WERR_INSUFFICIENT_BUFFER;
8981 goto out;
8984 if (!rpcbuf_alloc_size(buffer, *needed)) {
8985 result = WERR_NOMEM;
8986 goto out;
8989 smb_io_job_info_1("", buffer, info_1, 0);
8991 out:
8992 SAFE_FREE(info_1);
8994 return result;
8997 /****************************************************************************
8998 ****************************************************************************/
9000 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9001 NT_PRINTER_INFO_LEVEL *ntprinter,
9002 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9003 uint32 *needed)
9005 int i = 0;
9006 bool found = False;
9007 JOB_INFO_2 *info_2;
9008 WERROR result;
9009 DEVICEMODE *devmode = NULL;
9010 NT_DEVICEMODE *nt_devmode = NULL;
9012 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9013 return WERR_NOMEM;
9015 ZERO_STRUCTP(info_2);
9017 for ( i=0; i<count && found==False; i++ )
9019 if ((*queue)[i].job == (int)jobid)
9020 found = True;
9023 if ( !found ) {
9024 /* NT treats not found as bad param... yet another bad
9025 choice */
9026 result = WERR_INVALID_PARAM;
9027 goto done;
9031 * if the print job does not have a DEVMODE associated with it,
9032 * just use the one for the printer. A NULL devicemode is not
9033 * a failure condition
9036 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9037 devmode = construct_dev_mode(lp_const_servicename(snum));
9038 else {
9039 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9040 ZERO_STRUCTP( devmode );
9041 convert_nt_devicemode( devmode, nt_devmode );
9045 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9047 *needed += spoolss_size_job_info_2(info_2);
9049 if (*needed > offered) {
9050 result = WERR_INSUFFICIENT_BUFFER;
9051 goto done;
9054 if (!rpcbuf_alloc_size(buffer, *needed)) {
9055 result = WERR_NOMEM;
9056 goto done;
9059 smb_io_job_info_2("", buffer, info_2, 0);
9061 result = WERR_OK;
9063 done:
9064 /* Cleanup allocated memory */
9066 free_job_info_2(info_2); /* Also frees devmode */
9067 SAFE_FREE(info_2);
9069 return result;
9072 /****************************************************************************
9073 ****************************************************************************/
9075 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9077 POLICY_HND *handle = &q_u->handle;
9078 uint32 jobid = q_u->jobid;
9079 uint32 level = q_u->level;
9080 RPC_BUFFER *buffer = NULL;
9081 uint32 offered = q_u->offered;
9082 uint32 *needed = &r_u->needed;
9083 WERROR wstatus = WERR_OK;
9084 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9085 int snum;
9086 int count;
9087 print_queue_struct *queue = NULL;
9088 print_status_struct prt_status;
9090 /* that's an [in out] buffer */
9092 if (!q_u->buffer && (offered!=0)) {
9093 return WERR_INVALID_PARAM;
9096 rpcbuf_move(q_u->buffer, &r_u->buffer);
9097 buffer = r_u->buffer;
9099 DEBUG(5,("spoolss_getjob\n"));
9101 *needed = 0;
9103 if (!get_printer_snum(p, handle, &snum, NULL))
9104 return WERR_BADFID;
9106 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9107 if ( !W_ERROR_IS_OK(wstatus) )
9108 return wstatus;
9110 count = print_queue_status(snum, &queue, &prt_status);
9112 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9113 count, prt_status.status, prt_status.message));
9115 switch ( level ) {
9116 case 1:
9117 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9118 buffer, offered, needed);
9119 break;
9120 case 2:
9121 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9122 buffer, offered, needed);
9123 break;
9124 default:
9125 wstatus = WERR_UNKNOWN_LEVEL;
9126 break;
9129 SAFE_FREE(queue);
9130 free_a_printer( &ntprinter, 2 );
9132 return wstatus;
9135 /****************************************************************
9136 _spoolss_GetPrinterDataEx
9138 From MSDN documentation of GetPrinterDataEx: pass request
9139 to GetPrinterData if key is "PrinterDriverData".
9140 ****************************************************************/
9142 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9143 struct spoolss_GetPrinterDataEx *r)
9145 POLICY_HND *handle = r->in.handle;
9146 uint8 *data = NULL;
9147 const char *keyname = r->in.key_name;
9148 const char *valuename = r->in.value_name;
9150 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9152 NT_PRINTER_INFO_LEVEL *printer = NULL;
9153 int snum = 0;
9154 WERROR status = WERR_OK;
9156 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9158 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9159 keyname, valuename));
9161 /* in case of problem, return some default values */
9163 *r->out.needed = 0;
9164 *r->out.type = 0;
9166 if (!Printer) {
9167 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9168 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9169 status = WERR_BADFID;
9170 goto done;
9173 /* Is the handle to a printer or to the server? */
9175 if (Printer->printer_type == SPLHND_SERVER) {
9176 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9177 "Not implemented for server handles yet\n"));
9178 status = WERR_INVALID_PARAM;
9179 goto done;
9182 if ( !get_printer_snum(p,handle, &snum, NULL) )
9183 return WERR_BADFID;
9185 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9186 if ( !W_ERROR_IS_OK(status) )
9187 goto done;
9189 /* check to see if the keyname is valid */
9190 if ( !strlen(keyname) ) {
9191 status = WERR_INVALID_PARAM;
9192 goto done;
9195 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9196 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9197 "Invalid keyname [%s]\n", keyname ));
9198 free_a_printer( &printer, 2 );
9199 status = WERR_BADFILE;
9200 goto done;
9203 /* When given a new keyname, we should just create it */
9205 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9206 r->out.type, &data, r->out.needed,
9207 r->in.offered );
9209 if (*r->out.needed > r->in.offered) {
9210 status = WERR_MORE_DATA;
9213 if (W_ERROR_IS_OK(status)) {
9214 memcpy(r->out.buffer, data, r->in.offered);
9217 done:
9218 if ( printer )
9219 free_a_printer( &printer, 2 );
9221 return status;
9224 /****************************************************************
9225 _spoolss_SetPrinterDataEx
9226 ****************************************************************/
9228 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9229 struct spoolss_SetPrinterDataEx *r)
9231 POLICY_HND *handle = r->in.handle;
9232 NT_PRINTER_INFO_LEVEL *printer = NULL;
9233 int snum = 0;
9234 WERROR status = WERR_OK;
9235 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9236 char *oid_string;
9238 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9240 /* From MSDN documentation of SetPrinterDataEx: pass request to
9241 SetPrinterData if key is "PrinterDriverData" */
9243 if (!Printer) {
9244 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9245 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9246 return WERR_BADFID;
9249 if ( Printer->printer_type == SPLHND_SERVER ) {
9250 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9251 "Not implemented for server handles yet\n"));
9252 return WERR_INVALID_PARAM;
9255 if ( !get_printer_snum(p,handle, &snum, NULL) )
9256 return WERR_BADFID;
9259 * Access check : NT returns "access denied" if you make a
9260 * SetPrinterData call without the necessary privildge.
9261 * we were originally returning OK if nothing changed
9262 * which made Win2k issue **a lot** of SetPrinterData
9263 * when connecting to a printer --jerry
9266 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9268 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9269 "change denied by handle access permissions\n"));
9270 return WERR_ACCESS_DENIED;
9273 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9274 if (!W_ERROR_IS_OK(status))
9275 return status;
9277 /* check for OID in valuename */
9279 if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9281 *oid_string = '\0';
9282 oid_string++;
9285 /* save the registry data */
9287 status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9288 r->in.type, r->in.buffer, r->in.offered );
9290 if ( W_ERROR_IS_OK(status) )
9292 /* save the OID if one was specified */
9293 if ( oid_string ) {
9294 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9295 r->in.key_name, SPOOL_OID_KEY);
9296 if (!str) {
9297 return WERR_NOMEM;
9301 * I'm not checking the status here on purpose. Don't know
9302 * if this is right, but I'm returning the status from the
9303 * previous set_printer_dataex() call. I have no idea if
9304 * this is right. --jerry
9307 set_printer_dataex( printer, str, r->in.value_name,
9308 REG_SZ, (uint8 *)oid_string,
9309 strlen(oid_string)+1 );
9312 status = mod_a_printer(printer, 2);
9315 free_a_printer(&printer, 2);
9317 return status;
9320 /****************************************************************
9321 _spoolss_DeletePrinterDataEx
9322 ****************************************************************/
9324 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9325 struct spoolss_DeletePrinterDataEx *r)
9327 POLICY_HND *handle = r->in.handle;
9328 NT_PRINTER_INFO_LEVEL *printer = NULL;
9329 int snum=0;
9330 WERROR status = WERR_OK;
9331 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9333 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9335 if (!Printer) {
9336 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9337 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9338 return WERR_BADFID;
9341 if (!get_printer_snum(p, handle, &snum, NULL))
9342 return WERR_BADFID;
9344 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9345 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9346 "printer properties change denied by handle\n"));
9347 return WERR_ACCESS_DENIED;
9350 if (!r->in.value_name || !r->in.key_name) {
9351 return WERR_NOMEM;
9354 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9355 if (!W_ERROR_IS_OK(status))
9356 return status;
9358 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9360 if ( W_ERROR_IS_OK(status) )
9361 mod_a_printer( printer, 2 );
9363 free_a_printer(&printer, 2);
9365 return status;
9368 /********************************************************************
9369 * spoolss_enumprinterkey
9370 ********************************************************************/
9373 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9375 fstring key;
9376 fstring *keynames = NULL;
9377 uint16 *enumkeys = NULL;
9378 int num_keys;
9379 int printerkey_len;
9380 POLICY_HND *handle = &q_u->handle;
9381 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9382 NT_PRINTER_DATA *data;
9383 NT_PRINTER_INFO_LEVEL *printer = NULL;
9384 int snum = 0;
9385 WERROR status = WERR_BADFILE;
9388 DEBUG(4,("_spoolss_enumprinterkey\n"));
9390 if (!Printer) {
9391 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9392 return WERR_BADFID;
9395 if ( !get_printer_snum(p,handle, &snum, NULL) )
9396 return WERR_BADFID;
9398 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9399 if (!W_ERROR_IS_OK(status))
9400 return status;
9402 /* get the list of subkey names */
9404 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9405 data = printer->info_2->data;
9407 num_keys = get_printer_subkeys( data, key, &keynames );
9409 if ( num_keys == -1 ) {
9410 status = WERR_BADFILE;
9411 goto done;
9414 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9416 r_u->needed = printerkey_len*2;
9418 if ( q_u->size < r_u->needed ) {
9419 status = WERR_MORE_DATA;
9420 goto done;
9423 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9424 status = WERR_NOMEM;
9425 goto done;
9428 status = WERR_OK;
9430 if ( q_u->size < r_u->needed )
9431 status = WERR_MORE_DATA;
9433 done:
9434 free_a_printer( &printer, 2 );
9435 SAFE_FREE( keynames );
9437 return status;
9440 /****************************************************************
9441 _spoolss_DeletePrinterKey
9442 ****************************************************************/
9444 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9445 struct spoolss_DeletePrinterKey *r)
9447 POLICY_HND *handle = r->in.handle;
9448 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9449 NT_PRINTER_INFO_LEVEL *printer = NULL;
9450 int snum=0;
9451 WERROR status;
9453 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9455 if (!Printer) {
9456 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9457 OUR_HANDLE(handle)));
9458 return WERR_BADFID;
9461 /* if keyname == NULL, return error */
9463 if ( !r->in.key_name )
9464 return WERR_INVALID_PARAM;
9466 if (!get_printer_snum(p, handle, &snum, NULL))
9467 return WERR_BADFID;
9469 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9470 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9471 "printer properties change denied by handle\n"));
9472 return WERR_ACCESS_DENIED;
9475 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9476 if (!W_ERROR_IS_OK(status))
9477 return status;
9479 /* delete the key and all subneys */
9481 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9483 if ( W_ERROR_IS_OK(status) )
9484 status = mod_a_printer(printer, 2);
9486 free_a_printer( &printer, 2 );
9488 return status;
9492 /********************************************************************
9493 * spoolss_enumprinterdataex
9494 ********************************************************************/
9496 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9498 POLICY_HND *handle = &q_u->handle;
9499 uint32 in_size = q_u->size;
9500 uint32 num_entries,
9501 needed;
9502 NT_PRINTER_INFO_LEVEL *printer = NULL;
9503 PRINTER_ENUM_VALUES *enum_values = NULL;
9504 NT_PRINTER_DATA *p_data;
9505 fstring key;
9506 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9507 int snum;
9508 WERROR result;
9509 int key_index;
9510 int i;
9511 REGISTRY_VALUE *val;
9512 char *value_name;
9513 uint32 data_len;
9516 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9518 if (!Printer) {
9519 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9520 return WERR_BADFID;
9524 * first check for a keyname of NULL or "". Win2k seems to send
9525 * this a lot and we should send back WERR_INVALID_PARAM
9526 * no need to spend time looking up the printer in this case.
9527 * --jerry
9530 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9531 if ( !strlen(key) ) {
9532 result = WERR_INVALID_PARAM;
9533 goto done;
9536 /* get the printer off of disk */
9538 if (!get_printer_snum(p,handle, &snum, NULL))
9539 return WERR_BADFID;
9541 ZERO_STRUCT(printer);
9542 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9543 if (!W_ERROR_IS_OK(result))
9544 return result;
9546 /* now look for a match on the key name */
9548 p_data = printer->info_2->data;
9550 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9551 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9553 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9554 result = WERR_INVALID_PARAM;
9555 goto done;
9558 result = WERR_OK;
9559 needed = 0;
9561 /* allocate the memory for the array of pointers -- if necessary */
9563 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9564 if ( num_entries )
9566 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9568 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9569 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9570 result = WERR_NOMEM;
9571 goto done;
9574 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9578 * loop through all params and build the array to pass
9579 * back to the client
9582 for ( i=0; i<num_entries; i++ )
9584 /* lookup the registry value */
9586 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9587 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9589 /* copy the data */
9591 value_name = regval_name( val );
9592 init_unistr( &enum_values[i].valuename, value_name );
9593 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9594 enum_values[i].type = regval_type( val );
9596 data_len = regval_size( val );
9597 if ( data_len ) {
9598 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9600 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9601 data_len ));
9602 result = WERR_NOMEM;
9603 goto done;
9606 enum_values[i].data_len = data_len;
9608 /* keep track of the size of the array in bytes */
9610 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9613 /* housekeeping information in the reply */
9615 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9616 * the hand marshalled container size is a multiple
9617 * of 4 bytes for RPC alignment.
9620 if (needed % 4) {
9621 needed += 4-(needed % 4);
9624 r_u->needed = needed;
9625 r_u->returned = num_entries;
9627 if (needed > in_size) {
9628 result = WERR_MORE_DATA;
9629 goto done;
9632 /* copy data into the reply */
9634 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9635 response buffer size is != the offered buffer size
9637 r_u->ctr.size = r_u->needed;
9639 r_u->ctr.size = in_size;
9641 r_u->ctr.size_of_array = r_u->returned;
9642 r_u->ctr.values = enum_values;
9644 done:
9645 if ( printer )
9646 free_a_printer(&printer, 2);
9648 return result;
9651 /****************************************************************************
9652 ****************************************************************************/
9654 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9656 init_unistr(&info->name, name);
9659 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9660 UNISTR2 *environment,
9661 RPC_BUFFER *buffer,
9662 uint32 offered,
9663 uint32 *needed)
9665 char *long_archi = NULL;
9666 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9667 WERROR result = WERR_OK;
9668 TALLOC_CTX *ctx = talloc_tos();
9670 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9671 if (!long_archi) {
9672 return WERR_NOMEM;
9675 if (!get_short_archi(long_archi))
9676 return WERR_INVALID_ENVIRONMENT;
9678 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9679 return WERR_NOMEM;
9681 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9683 *needed += spoolss_size_printprocessordirectory_info_1(info);
9685 if (*needed > offered) {
9686 result = WERR_INSUFFICIENT_BUFFER;
9687 goto out;
9690 if (!rpcbuf_alloc_size(buffer, *needed)) {
9691 result = WERR_INSUFFICIENT_BUFFER;
9692 goto out;
9695 smb_io_printprocessordirectory_1("", buffer, info, 0);
9697 out:
9698 SAFE_FREE(info);
9700 return result;
9703 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9705 uint32 level = q_u->level;
9706 RPC_BUFFER *buffer = NULL;
9707 uint32 offered = q_u->offered;
9708 uint32 *needed = &r_u->needed;
9709 WERROR result;
9711 /* that's an [in out] buffer */
9713 if (!q_u->buffer && (offered!=0)) {
9714 return WERR_INVALID_PARAM;
9717 rpcbuf_move(q_u->buffer, &r_u->buffer);
9718 buffer = r_u->buffer;
9720 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9722 *needed=0;
9724 switch(level) {
9725 case 1:
9726 result = getprintprocessordirectory_level_1
9727 (&q_u->name, &q_u->environment, buffer, offered, needed);
9728 break;
9729 default:
9730 result = WERR_UNKNOWN_LEVEL;
9733 return result;
9736 /*******************************************************************
9737 Streams the monitor UI DLL name in UNICODE
9738 *******************************************************************/
9740 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9741 RPC_BUFFER *out, uint32 *needed )
9743 const char *dllname = "tcpmonui.dll";
9745 *needed = (strlen(dllname)+1) * 2;
9747 if ( rpcbuf_get_size(out) < *needed ) {
9748 return WERR_INSUFFICIENT_BUFFER;
9751 if ( !make_monitorui_buf( out, dllname ) ) {
9752 return WERR_NOMEM;
9755 return WERR_OK;
9758 /*******************************************************************
9759 Create a new TCP/IP port
9760 *******************************************************************/
9762 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9763 RPC_BUFFER *out, uint32 *needed )
9765 NT_PORT_DATA_1 port1;
9766 TALLOC_CTX *ctx = talloc_tos();
9767 char *device_uri = NULL;
9769 ZERO_STRUCT( port1 );
9771 /* convert to our internal port data structure */
9773 if ( !convert_port_data_1( &port1, in ) ) {
9774 return WERR_NOMEM;
9777 /* create the device URI and call the add_port_hook() */
9779 switch ( port1.protocol ) {
9780 case PORT_PROTOCOL_DIRECT:
9781 device_uri = talloc_asprintf(ctx,
9782 "socket://%s:%d/", port1.hostaddr, port1.port );
9783 break;
9785 case PORT_PROTOCOL_LPR:
9786 device_uri = talloc_asprintf(ctx,
9787 "lpr://%s/%s", port1.hostaddr, port1.queue );
9788 break;
9790 default:
9791 return WERR_UNKNOWN_PORT;
9794 if (!device_uri) {
9795 return WERR_NOMEM;
9798 return add_port_hook(ctx, token, port1.name, device_uri );
9801 /*******************************************************************
9802 *******************************************************************/
9804 struct xcv_api_table xcvtcp_cmds[] = {
9805 { "MonitorUI", xcvtcp_monitorui },
9806 { "AddPort", xcvtcp_addport},
9807 { NULL, NULL }
9810 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9811 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9812 uint32 *needed )
9814 int i;
9816 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9818 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9819 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9820 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9823 return WERR_BADFUNC;
9826 /*******************************************************************
9827 *******************************************************************/
9828 #if 0 /* don't support management using the "Local Port" monitor */
9830 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9831 RPC_BUFFER *out, uint32 *needed )
9833 const char *dllname = "localui.dll";
9835 *needed = (strlen(dllname)+1) * 2;
9837 if ( rpcbuf_get_size(out) < *needed ) {
9838 return WERR_INSUFFICIENT_BUFFER;
9841 if ( !make_monitorui_buf( out, dllname )) {
9842 return WERR_NOMEM;
9845 return WERR_OK;
9848 /*******************************************************************
9849 *******************************************************************/
9851 struct xcv_api_table xcvlocal_cmds[] = {
9852 { "MonitorUI", xcvlocal_monitorui },
9853 { NULL, NULL }
9855 #else
9856 struct xcv_api_table xcvlocal_cmds[] = {
9857 { NULL, NULL }
9859 #endif
9863 /*******************************************************************
9864 *******************************************************************/
9866 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9867 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9868 uint32 *needed )
9870 int i;
9872 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9874 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9875 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9876 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9878 return WERR_BADFUNC;
9881 /*******************************************************************
9882 *******************************************************************/
9884 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9886 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9887 fstring command;
9889 if (!Printer) {
9890 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9891 return WERR_BADFID;
9894 /* Has to be a handle to the TCP/IP port monitor */
9896 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9897 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9898 return WERR_BADFID;
9901 /* requires administrative access to the server */
9903 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9904 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9905 return WERR_ACCESS_DENIED;
9908 /* Get the command name. There's numerous commands supported by the
9909 TCPMON interface. */
9911 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9912 q_u->dataname.uni_str_len*2, 0);
9914 /* Allocate the outgoing buffer */
9916 if (!rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx ))
9917 return WERR_NOMEM;
9919 switch ( Printer->printer_type ) {
9920 case SPLHND_PORTMON_TCP:
9921 return process_xcvtcp_command( p->server_info->ptok, command,
9922 &q_u->indata, &r_u->outdata, &r_u->needed );
9923 case SPLHND_PORTMON_LOCAL:
9924 return process_xcvlocal_command( p->server_info->ptok, command,
9925 &q_u->indata, &r_u->outdata, &r_u->needed );
9928 return WERR_INVALID_PRINT_MONITOR;
9931 /****************************************************************
9932 _spoolss_AddPrintProcessor
9933 ****************************************************************/
9935 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9936 struct spoolss_AddPrintProcessor *r)
9938 /* for now, just indicate success and ignore the add. We'll
9939 automatically set the winprint processor for printer
9940 entries later. Used to debug the LexMark Optra S 1855 PCL
9941 driver --jerry */
9943 return WERR_OK;
9946 /****************************************************************
9947 _spoolss_EnumPrinters
9948 ****************************************************************/
9950 WERROR _spoolss_EnumPrinters(pipes_struct *p,
9951 struct spoolss_EnumPrinters *r)
9953 p->rng_fault_state = true;
9954 return WERR_NOT_SUPPORTED;
9957 /****************************************************************
9958 _spoolss_GetJob
9959 ****************************************************************/
9961 WERROR _spoolss_GetJob(pipes_struct *p,
9962 struct spoolss_GetJob *r)
9964 p->rng_fault_state = true;
9965 return WERR_NOT_SUPPORTED;
9968 /****************************************************************
9969 _spoolss_EnumJobs
9970 ****************************************************************/
9972 WERROR _spoolss_EnumJobs(pipes_struct *p,
9973 struct spoolss_EnumJobs *r)
9975 p->rng_fault_state = true;
9976 return WERR_NOT_SUPPORTED;
9979 /****************************************************************
9980 _spoolss_AddPrinter
9981 ****************************************************************/
9983 WERROR _spoolss_AddPrinter(pipes_struct *p,
9984 struct spoolss_AddPrinter *r)
9986 p->rng_fault_state = true;
9987 return WERR_NOT_SUPPORTED;
9990 /****************************************************************
9991 _spoolss_SetPrinter
9992 ****************************************************************/
9994 WERROR _spoolss_SetPrinter(pipes_struct *p,
9995 struct spoolss_SetPrinter *r)
9997 p->rng_fault_state = true;
9998 return WERR_NOT_SUPPORTED;
10001 /****************************************************************
10002 _spoolss_GetPrinter
10003 ****************************************************************/
10005 WERROR _spoolss_GetPrinter(pipes_struct *p,
10006 struct spoolss_GetPrinter *r)
10008 p->rng_fault_state = true;
10009 return WERR_NOT_SUPPORTED;
10012 /****************************************************************
10013 _spoolss_AddPrinterDriver
10014 ****************************************************************/
10016 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
10017 struct spoolss_AddPrinterDriver *r)
10019 p->rng_fault_state = true;
10020 return WERR_NOT_SUPPORTED;
10023 /****************************************************************
10024 _spoolss_EnumPrinterDrivers
10025 ****************************************************************/
10027 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10028 struct spoolss_EnumPrinterDrivers *r)
10030 p->rng_fault_state = true;
10031 return WERR_NOT_SUPPORTED;
10034 /****************************************************************
10035 _spoolss_GetPrinterDriver
10036 ****************************************************************/
10038 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10039 struct spoolss_GetPrinterDriver *r)
10041 p->rng_fault_state = true;
10042 return WERR_NOT_SUPPORTED;
10045 /****************************************************************
10046 _spoolss_GetPrinterDriverDirectory
10047 ****************************************************************/
10049 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
10050 struct spoolss_GetPrinterDriverDirectory *r)
10052 p->rng_fault_state = true;
10053 return WERR_NOT_SUPPORTED;
10056 /****************************************************************
10057 _spoolss_EnumPrintProcessors
10058 ****************************************************************/
10060 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10061 struct spoolss_EnumPrintProcessors *r)
10063 p->rng_fault_state = true;
10064 return WERR_NOT_SUPPORTED;
10067 /****************************************************************
10068 _spoolss_GetPrintProcessorDirectory
10069 ****************************************************************/
10071 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
10072 struct spoolss_GetPrintProcessorDirectory *r)
10074 p->rng_fault_state = true;
10075 return WERR_NOT_SUPPORTED;
10078 /****************************************************************
10079 _spoolss_ReadPrinter
10080 ****************************************************************/
10082 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10083 struct spoolss_ReadPrinter *r)
10085 p->rng_fault_state = true;
10086 return WERR_NOT_SUPPORTED;
10089 /****************************************************************
10090 _spoolss_GetPrinterData
10091 ****************************************************************/
10093 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10094 struct spoolss_GetPrinterData *r)
10096 p->rng_fault_state = true;
10097 return WERR_NOT_SUPPORTED;
10100 /****************************************************************
10101 _spoolss_SetPrinterData
10102 ****************************************************************/
10104 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10105 struct spoolss_SetPrinterData *r)
10107 p->rng_fault_state = true;
10108 return WERR_NOT_SUPPORTED;
10111 /****************************************************************
10112 _spoolss_WaitForPrinterChange
10113 ****************************************************************/
10115 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10116 struct spoolss_WaitForPrinterChange *r)
10118 p->rng_fault_state = true;
10119 return WERR_NOT_SUPPORTED;
10122 /****************************************************************
10123 _spoolss_EnumForms
10124 ****************************************************************/
10126 WERROR _spoolss_EnumForms(pipes_struct *p,
10127 struct spoolss_EnumForms *r)
10129 p->rng_fault_state = true;
10130 return WERR_NOT_SUPPORTED;
10133 /****************************************************************
10134 _spoolss_EnumPorts
10135 ****************************************************************/
10137 WERROR _spoolss_EnumPorts(pipes_struct *p,
10138 struct spoolss_EnumPorts *r)
10140 p->rng_fault_state = true;
10141 return WERR_NOT_SUPPORTED;
10144 /****************************************************************
10145 _spoolss_EnumMonitors
10146 ****************************************************************/
10148 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10149 struct spoolss_EnumMonitors *r)
10151 p->rng_fault_state = true;
10152 return WERR_NOT_SUPPORTED;
10155 /****************************************************************
10156 _spoolss_AddPort
10157 ****************************************************************/
10159 WERROR _spoolss_AddPort(pipes_struct *p,
10160 struct spoolss_AddPort *r)
10162 p->rng_fault_state = true;
10163 return WERR_NOT_SUPPORTED;
10166 /****************************************************************
10167 _spoolss_ConfigurePort
10168 ****************************************************************/
10170 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10171 struct spoolss_ConfigurePort *r)
10173 p->rng_fault_state = true;
10174 return WERR_NOT_SUPPORTED;
10177 /****************************************************************
10178 _spoolss_DeletePort
10179 ****************************************************************/
10181 WERROR _spoolss_DeletePort(pipes_struct *p,
10182 struct spoolss_DeletePort *r)
10184 p->rng_fault_state = true;
10185 return WERR_NOT_SUPPORTED;
10188 /****************************************************************
10189 _spoolss_CreatePrinterIC
10190 ****************************************************************/
10192 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10193 struct spoolss_CreatePrinterIC *r)
10195 p->rng_fault_state = true;
10196 return WERR_NOT_SUPPORTED;
10199 /****************************************************************
10200 _spoolss_PlayGDIScriptOnPrinterIC
10201 ****************************************************************/
10203 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10204 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10206 p->rng_fault_state = true;
10207 return WERR_NOT_SUPPORTED;
10210 /****************************************************************
10211 _spoolss_DeletePrinterIC
10212 ****************************************************************/
10214 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10215 struct spoolss_DeletePrinterIC *r)
10217 p->rng_fault_state = true;
10218 return WERR_NOT_SUPPORTED;
10221 /****************************************************************
10222 _spoolss_AddPrinterConnection
10223 ****************************************************************/
10225 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10226 struct spoolss_AddPrinterConnection *r)
10228 p->rng_fault_state = true;
10229 return WERR_NOT_SUPPORTED;
10232 /****************************************************************
10233 _spoolss_DeletePrinterConnection
10234 ****************************************************************/
10236 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10237 struct spoolss_DeletePrinterConnection *r)
10239 p->rng_fault_state = true;
10240 return WERR_NOT_SUPPORTED;
10243 /****************************************************************
10244 _spoolss_PrinterMessageBox
10245 ****************************************************************/
10247 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10248 struct spoolss_PrinterMessageBox *r)
10250 p->rng_fault_state = true;
10251 return WERR_NOT_SUPPORTED;
10254 /****************************************************************
10255 _spoolss_AddMonitor
10256 ****************************************************************/
10258 WERROR _spoolss_AddMonitor(pipes_struct *p,
10259 struct spoolss_AddMonitor *r)
10261 p->rng_fault_state = true;
10262 return WERR_NOT_SUPPORTED;
10265 /****************************************************************
10266 _spoolss_DeleteMonitor
10267 ****************************************************************/
10269 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10270 struct spoolss_DeleteMonitor *r)
10272 p->rng_fault_state = true;
10273 return WERR_NOT_SUPPORTED;
10276 /****************************************************************
10277 _spoolss_DeletePrintProcessor
10278 ****************************************************************/
10280 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10281 struct spoolss_DeletePrintProcessor *r)
10283 p->rng_fault_state = true;
10284 return WERR_NOT_SUPPORTED;
10287 /****************************************************************
10288 _spoolss_AddPrintProvidor
10289 ****************************************************************/
10291 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10292 struct spoolss_AddPrintProvidor *r)
10294 p->rng_fault_state = true;
10295 return WERR_NOT_SUPPORTED;
10298 /****************************************************************
10299 _spoolss_DeletePrintProvidor
10300 ****************************************************************/
10302 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10303 struct spoolss_DeletePrintProvidor *r)
10305 p->rng_fault_state = true;
10306 return WERR_NOT_SUPPORTED;
10309 /****************************************************************
10310 _spoolss_EnumPrintProcDataTypes
10311 ****************************************************************/
10313 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10314 struct spoolss_EnumPrintProcDataTypes *r)
10316 p->rng_fault_state = true;
10317 return WERR_NOT_SUPPORTED;
10320 /****************************************************************
10321 _spoolss_ResetPrinter
10322 ****************************************************************/
10324 WERROR _spoolss_ResetPrinter(pipes_struct *p,
10325 struct spoolss_ResetPrinter *r)
10327 p->rng_fault_state = true;
10328 return WERR_NOT_SUPPORTED;
10331 /****************************************************************
10332 _spoolss_GetPrinterDriver2
10333 ****************************************************************/
10335 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10336 struct spoolss_GetPrinterDriver2 *r)
10338 p->rng_fault_state = true;
10339 return WERR_NOT_SUPPORTED;
10342 /****************************************************************
10343 _spoolss_FindFirstPrinterChangeNotification
10344 ****************************************************************/
10346 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10347 struct spoolss_FindFirstPrinterChangeNotification *r)
10349 p->rng_fault_state = true;
10350 return WERR_NOT_SUPPORTED;
10353 /****************************************************************
10354 _spoolss_FindNextPrinterChangeNotification
10355 ****************************************************************/
10357 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10358 struct spoolss_FindNextPrinterChangeNotification *r)
10360 p->rng_fault_state = true;
10361 return WERR_NOT_SUPPORTED;
10364 /****************************************************************
10365 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10366 ****************************************************************/
10368 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10369 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10371 p->rng_fault_state = true;
10372 return WERR_NOT_SUPPORTED;
10375 /****************************************************************
10376 _spoolss_ReplyOpenPrinter
10377 ****************************************************************/
10379 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10380 struct spoolss_ReplyOpenPrinter *r)
10382 p->rng_fault_state = true;
10383 return WERR_NOT_SUPPORTED;
10386 /****************************************************************
10387 _spoolss_RouterReplyPrinter
10388 ****************************************************************/
10390 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10391 struct spoolss_RouterReplyPrinter *r)
10393 p->rng_fault_state = true;
10394 return WERR_NOT_SUPPORTED;
10397 /****************************************************************
10398 _spoolss_ReplyClosePrinter
10399 ****************************************************************/
10401 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10402 struct spoolss_ReplyClosePrinter *r)
10404 p->rng_fault_state = true;
10405 return WERR_NOT_SUPPORTED;
10408 /****************************************************************
10409 _spoolss_AddPortEx
10410 ****************************************************************/
10412 WERROR _spoolss_AddPortEx(pipes_struct *p,
10413 struct spoolss_AddPortEx *r)
10415 p->rng_fault_state = true;
10416 return WERR_NOT_SUPPORTED;
10419 /****************************************************************
10420 _spoolss_RouterFindFirstPrinterChangeNotification
10421 ****************************************************************/
10423 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10424 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10426 p->rng_fault_state = true;
10427 return WERR_NOT_SUPPORTED;
10430 /****************************************************************
10431 _spoolss_SpoolerInit
10432 ****************************************************************/
10434 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10435 struct spoolss_SpoolerInit *r)
10437 p->rng_fault_state = true;
10438 return WERR_NOT_SUPPORTED;
10441 /****************************************************************
10442 _spoolss_ResetPrinterEx
10443 ****************************************************************/
10445 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10446 struct spoolss_ResetPrinterEx *r)
10448 p->rng_fault_state = true;
10449 return WERR_NOT_SUPPORTED;
10452 /****************************************************************
10453 _spoolss_RemoteFindFirstPrinterChangeNotifyEx
10454 ****************************************************************/
10456 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
10457 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
10459 p->rng_fault_state = true;
10460 return WERR_NOT_SUPPORTED;
10463 /****************************************************************
10464 _spoolss_RouterReplyPrinterEx
10465 ****************************************************************/
10467 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10468 struct spoolss_RouterReplyPrinterEx *r)
10470 p->rng_fault_state = true;
10471 return WERR_NOT_SUPPORTED;
10474 /****************************************************************
10475 _dcesrv_spoolss_RouterRefreshPrinterChangeNotify
10476 ****************************************************************/
10478 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
10479 struct spoolss_RouterRefreshPrinterChangeNotify *r)
10481 p->rng_fault_state = true;
10482 return WERR_NOT_SUPPORTED;
10485 /****************************************************************
10486 _spoolss_44
10487 ****************************************************************/
10489 WERROR _spoolss_44(pipes_struct *p,
10490 struct spoolss_44 *r)
10492 p->rng_fault_state = true;
10493 return WERR_NOT_SUPPORTED;
10496 /****************************************************************
10497 _spoolss_AddPrinterEx
10498 ****************************************************************/
10500 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
10501 struct spoolss_AddPrinterEx *r)
10503 p->rng_fault_state = true;
10504 return WERR_NOT_SUPPORTED;
10507 /****************************************************************
10508 _spoolss_47
10509 ****************************************************************/
10511 WERROR _spoolss_47(pipes_struct *p,
10512 struct spoolss_47 *r)
10514 p->rng_fault_state = true;
10515 return WERR_NOT_SUPPORTED;
10518 /****************************************************************
10519 _spoolss_EnumPrinterData
10520 ****************************************************************/
10522 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10523 struct spoolss_EnumPrinterData *r)
10525 p->rng_fault_state = true;
10526 return WERR_NOT_SUPPORTED;
10529 /****************************************************************
10530 _spoolss_4a
10531 ****************************************************************/
10533 WERROR _spoolss_4a(pipes_struct *p,
10534 struct spoolss_4a *r)
10536 p->rng_fault_state = true;
10537 return WERR_NOT_SUPPORTED;
10540 /****************************************************************
10541 _spoolss_4b
10542 ****************************************************************/
10544 WERROR _spoolss_4b(pipes_struct *p,
10545 struct spoolss_4b *r)
10547 p->rng_fault_state = true;
10548 return WERR_NOT_SUPPORTED;
10551 /****************************************************************
10552 _spoolss_4c
10553 ****************************************************************/
10555 WERROR _spoolss_4c(pipes_struct *p,
10556 struct spoolss_4c *r)
10558 p->rng_fault_state = true;
10559 return WERR_NOT_SUPPORTED;
10562 /****************************************************************
10563 _spoolss_EnumPrinterDataEx
10564 ****************************************************************/
10566 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10567 struct spoolss_EnumPrinterDataEx *r)
10569 p->rng_fault_state = true;
10570 return WERR_NOT_SUPPORTED;
10573 /****************************************************************
10574 _spoolss_EnumPrinterKey
10575 ****************************************************************/
10577 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10578 struct spoolss_EnumPrinterKey *r)
10580 p->rng_fault_state = true;
10581 return WERR_NOT_SUPPORTED;
10584 /****************************************************************
10585 _spoolss_53
10586 ****************************************************************/
10588 WERROR _spoolss_53(pipes_struct *p,
10589 struct spoolss_53 *r)
10591 p->rng_fault_state = true;
10592 return WERR_NOT_SUPPORTED;
10595 /****************************************************************
10596 _spoolss_55
10597 ****************************************************************/
10599 WERROR _spoolss_55(pipes_struct *p,
10600 struct spoolss_55 *r)
10602 p->rng_fault_state = true;
10603 return WERR_NOT_SUPPORTED;
10606 /****************************************************************
10607 _spoolss_56
10608 ****************************************************************/
10610 WERROR _spoolss_56(pipes_struct *p,
10611 struct spoolss_56 *r)
10613 p->rng_fault_state = true;
10614 return WERR_NOT_SUPPORTED;
10617 /****************************************************************
10618 _spoolss_57
10619 ****************************************************************/
10621 WERROR _spoolss_57(pipes_struct *p,
10622 struct spoolss_57 *r)
10624 p->rng_fault_state = true;
10625 return WERR_NOT_SUPPORTED;
10628 /****************************************************************
10629 _spoolss_XcvData
10630 ****************************************************************/
10632 WERROR _spoolss_XcvData(pipes_struct *p,
10633 struct spoolss_XcvData *r)
10635 p->rng_fault_state = true;
10636 return WERR_NOT_SUPPORTED;
10639 /****************************************************************
10640 _spoolss_AddPrinterDriverEx
10641 ****************************************************************/
10643 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
10644 struct spoolss_AddPrinterDriverEx *r)
10646 p->rng_fault_state = true;
10647 return WERR_NOT_SUPPORTED;
10650 /****************************************************************
10651 _spoolss_5a
10652 ****************************************************************/
10654 WERROR _spoolss_5a(pipes_struct *p,
10655 struct spoolss_5a *r)
10657 p->rng_fault_state = true;
10658 return WERR_NOT_SUPPORTED;
10661 /****************************************************************
10662 _spoolss_5b
10663 ****************************************************************/
10665 WERROR _spoolss_5b(pipes_struct *p,
10666 struct spoolss_5b *r)
10668 p->rng_fault_state = true;
10669 return WERR_NOT_SUPPORTED;
10672 /****************************************************************
10673 _spoolss_5c
10674 ****************************************************************/
10676 WERROR _spoolss_5c(pipes_struct *p,
10677 struct spoolss_5c *r)
10679 p->rng_fault_state = true;
10680 return WERR_NOT_SUPPORTED;
10683 /****************************************************************
10684 _spoolss_5d
10685 ****************************************************************/
10687 WERROR _spoolss_5d(pipes_struct *p,
10688 struct spoolss_5d *r)
10690 p->rng_fault_state = true;
10691 return WERR_NOT_SUPPORTED;
10694 /****************************************************************
10695 _spoolss_5e
10696 ****************************************************************/
10698 WERROR _spoolss_5e(pipes_struct *p,
10699 struct spoolss_5e *r)
10701 p->rng_fault_state = true;
10702 return WERR_NOT_SUPPORTED;
10705 /****************************************************************
10706 _spoolss_5f
10707 ****************************************************************/
10709 WERROR _spoolss_5f(pipes_struct *p,
10710 struct spoolss_5f *r)
10712 p->rng_fault_state = true;
10713 return WERR_NOT_SUPPORTED;