s3: Add talloc_dict.[ch]
[Samba/aatanasov.git] / source3 / rpc_server / srv_spoolss_nt.c
blobe535f26a83012822e00ad1cb9ed993904bd7994d
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.
10 * Copyright (C) Guenther Deschner 2009.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33 ((info)?ndr_size_##fn(info, level, ic, 0):0)
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44 extern userdom_struct current_user_info;
46 #undef DBGC_CLASS
47 #define DBGC_CLASS DBGC_RPC_SRV
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
51 #endif
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
56 static Printer_entry *printers_list;
58 typedef struct _counter_printer_0 {
59 struct _counter_printer_0 *next;
60 struct _counter_printer_0 *prev;
62 int snum;
63 uint32_t counter;
64 } counter_printer_0;
66 static counter_printer_0 *counter_list;
68 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
69 static uint32_t smb_connections = 0;
72 /* in printing/nt_printing.c */
74 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
76 /* API table for Xcv Monitor functions */
78 struct xcv_api_table {
79 const char *name;
80 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 /********************************************************************
84 * Canonicalize servername.
85 ********************************************************************/
87 static const char *canon_servername(const char *servername)
89 const char *pservername = servername;
90 while (*pservername == '\\') {
91 pservername++;
93 return pservername;
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v)
99 switch (v) {
100 case LPQ_QUEUED:
101 return 0;
102 case LPQ_PAUSED:
103 return JOB_STATUS_PAUSED;
104 case LPQ_SPOOLING:
105 return JOB_STATUS_SPOOLING;
106 case LPQ_PRINTING:
107 return JOB_STATUS_PRINTING;
108 case LPQ_ERROR:
109 return JOB_STATUS_ERROR;
110 case LPQ_DELETING:
111 return JOB_STATUS_DELETING;
112 case LPQ_OFFLINE:
113 return JOB_STATUS_OFFLINE;
114 case LPQ_PAPEROUT:
115 return JOB_STATUS_PAPEROUT;
116 case LPQ_PRINTED:
117 return JOB_STATUS_PRINTED;
118 case LPQ_DELETED:
119 return JOB_STATUS_DELETED;
120 case LPQ_BLOCKED:
121 return JOB_STATUS_BLOCKED_DEVQ;
122 case LPQ_USER_INTERVENTION:
123 return JOB_STATUS_USER_INTERVENTION;
125 return 0;
128 static int nt_printq_status(int v)
130 switch (v) {
131 case LPQ_PAUSED:
132 return PRINTER_STATUS_PAUSED;
133 case LPQ_QUEUED:
134 case LPQ_SPOOLING:
135 case LPQ_PRINTING:
136 return 0;
138 return 0;
141 /***************************************************************************
142 Disconnect from the client
143 ****************************************************************************/
145 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
147 WERROR result;
148 NTSTATUS status;
151 * Tell the specific printing tdb we no longer want messages for this printer
152 * by deregistering our PID.
155 if (!print_notify_deregister_pid(snum))
156 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
158 /* weird if the test succeds !!! */
159 if (smb_connections==0) {
160 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161 return;
164 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
165 handle,
166 &result);
167 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
168 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
169 win_errstr(result)));
171 /* if it's the last connection, deconnect the IPC$ share */
172 if (smb_connections==1) {
174 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
175 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
177 messaging_deregister(smbd_messaging_context(),
178 MSG_PRINTER_NOTIFY2, NULL);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
186 smb_connections--;
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static int printer_entry_destructor(Printer_entry *Printer)
195 if (Printer->notify.client_connected == true) {
196 int snum = -1;
198 if ( Printer->printer_type == SPLHND_SERVER) {
199 snum = -1;
200 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
201 } else if (Printer->printer_type == SPLHND_PRINTER) {
202 snum = print_queue_snum(Printer->sharename);
203 if (snum != -1)
204 srv_spoolss_replycloseprinter(snum,
205 &Printer->notify.client_hnd);
209 Printer->notify.flags=0;
210 Printer->notify.options=0;
211 Printer->notify.localmachine[0]='\0';
212 Printer->notify.printerlocal=0;
213 TALLOC_FREE(Printer->notify.option);
214 Printer->notify.client_connected = false;
216 free_nt_devicemode( &Printer->nt_devmode );
217 free_a_printer( &Printer->printer_info, 2 );
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list, Printer);
221 return 0;
224 /****************************************************************************
225 find printer index by handle
226 ****************************************************************************/
228 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
229 struct policy_handle *hnd)
231 Printer_entry *find_printer = NULL;
233 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
234 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
235 return NULL;
238 return find_printer;
241 /****************************************************************************
242 Close printer index by handle.
243 ****************************************************************************/
245 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
247 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
249 if (!Printer) {
250 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
251 OUR_HANDLE(hnd)));
252 return false;
255 close_policy_hnd(p, hnd);
257 return true;
260 /****************************************************************************
261 Delete a printer given a handle.
262 ****************************************************************************/
264 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
266 char *cmd = lp_deleteprinter_cmd();
267 char *command = NULL;
268 int ret;
269 SE_PRIV se_printop = SE_PRINT_OPERATOR;
270 bool is_print_op = false;
272 /* can't fail if we don't try */
274 if ( !*cmd )
275 return WERR_OK;
277 command = talloc_asprintf(ctx,
278 "%s \"%s\"",
279 cmd, sharename);
280 if (!command) {
281 return WERR_NOMEM;
283 if ( token )
284 is_print_op = user_has_privileges( token, &se_printop );
286 DEBUG(10,("Running [%s]\n", command));
288 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
290 if ( is_print_op )
291 become_root();
293 if ( (ret = smbrun(command, NULL)) == 0 ) {
294 /* Tell everyone we updated smb.conf. */
295 message_send_all(smbd_messaging_context(),
296 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
299 if ( is_print_op )
300 unbecome_root();
302 /********** END SePrintOperatorPrivlege BLOCK **********/
304 DEBUGADD(10,("returned [%d]\n", ret));
306 TALLOC_FREE(command);
308 if (ret != 0)
309 return WERR_BADFID; /* What to return here? */
311 /* go ahead and re-read the services immediately */
312 become_root();
313 reload_services(false);
314 unbecome_root();
316 if ( lp_servicenumber( sharename ) < 0 )
317 return WERR_ACCESS_DENIED;
319 return WERR_OK;
322 /****************************************************************************
323 Delete a printer given a handle.
324 ****************************************************************************/
326 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
328 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
330 if (!Printer) {
331 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
332 OUR_HANDLE(hnd)));
333 return WERR_BADFID;
337 * It turns out that Windows allows delete printer on a handle
338 * opened by an admin user, then used on a pipe handle created
339 * by an anonymous user..... but they're working on security.... riiight !
340 * JRA.
343 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
344 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
345 return WERR_ACCESS_DENIED;
348 /* this does not need a become root since the access check has been
349 done on the handle already */
351 if (del_a_printer( Printer->sharename ) != 0) {
352 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
353 return WERR_BADFID;
356 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
357 Printer->sharename );
360 /****************************************************************************
361 Return the snum of a printer corresponding to an handle.
362 ****************************************************************************/
364 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
365 int *number, struct share_params **params)
367 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
369 if (!Printer) {
370 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
371 OUR_HANDLE(hnd)));
372 return false;
375 switch (Printer->printer_type) {
376 case SPLHND_PRINTER:
377 DEBUG(4,("short name:%s\n", Printer->sharename));
378 *number = print_queue_snum(Printer->sharename);
379 return (*number != -1);
380 case SPLHND_SERVER:
381 return false;
382 default:
383 return false;
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
398 return false;
401 /* it's a print server */
402 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = SPLHND_SERVER;
406 /* it's a printer (set_printer_hnd_name() will handle port monitors */
407 else {
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = SPLHND_PRINTER;
412 return true;
415 /****************************************************************************
416 Set printer handle name.. Accept names like \\server, \\server\printer,
417 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
418 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
419 XcvDataPort() interface.
420 ****************************************************************************/
422 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
424 int snum;
425 int n_services=lp_numservices();
426 char *aprinter, *printername;
427 const char *servername;
428 fstring sname;
429 bool found = false;
430 NT_PRINTER_INFO_LEVEL *printer = NULL;
431 WERROR result;
433 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
434 (unsigned long)strlen(handlename)));
436 aprinter = CONST_DISCARD(char *, handlename);
437 if ( *handlename == '\\' ) {
438 servername = canon_servername(handlename);
439 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
440 *aprinter = '\0';
441 aprinter++;
443 } else {
444 servername = global_myname();
447 /* save the servername to fill in replies on this handle */
449 if ( !is_myname_or_ipaddr( servername ) )
450 return false;
452 fstrcpy( Printer->servername, servername );
454 if ( Printer->printer_type == SPLHND_SERVER )
455 return true;
457 if ( Printer->printer_type != SPLHND_PRINTER )
458 return false;
460 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
462 /* check for the Port Monitor Interface */
464 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
465 Printer->printer_type = SPLHND_PORTMON_TCP;
466 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
467 found = true;
469 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
470 Printer->printer_type = SPLHND_PORTMON_LOCAL;
471 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
472 found = true;
475 /* Search all sharenames first as this is easier than pulling
476 the printer_info_2 off of disk. Don't use find_service() since
477 that calls out to map_username() */
479 /* do another loop to look for printernames */
481 for (snum=0; !found && snum<n_services; snum++) {
483 /* no point going on if this is not a printer */
485 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
486 continue;
488 fstrcpy(sname, lp_servicename(snum));
489 if ( strequal( aprinter, sname ) ) {
490 found = true;
491 break;
494 /* no point looking up the printer object if
495 we aren't allowing printername != sharename */
497 if ( lp_force_printername(snum) )
498 continue;
500 fstrcpy(sname, lp_servicename(snum));
502 printer = NULL;
504 /* This call doesn't fill in the location or comment from
505 * a CUPS server for efficiency with large numbers of printers.
506 * JRA.
509 result = get_a_printer_search( NULL, &printer, 2, sname );
510 if ( !W_ERROR_IS_OK(result) ) {
511 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
512 sname, win_errstr(result)));
513 continue;
516 /* printername is always returned as \\server\printername */
517 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
518 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
519 printer->info_2->printername));
520 free_a_printer( &printer, 2);
521 continue;
524 printername++;
526 if ( strequal(printername, aprinter) ) {
527 free_a_printer( &printer, 2);
528 found = true;
529 break;
532 DEBUGADD(10, ("printername: %s\n", printername));
534 free_a_printer( &printer, 2);
537 free_a_printer( &printer, 2);
539 if ( !found ) {
540 DEBUGADD(4,("Printer not found\n"));
541 return false;
544 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
546 fstrcpy(Printer->sharename, sname);
548 return true;
551 /****************************************************************************
552 Find first available printer slot. creates a printer handle for you.
553 ****************************************************************************/
555 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
556 const char *name, uint32_t access_granted)
558 Printer_entry *new_printer;
560 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
562 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
563 if (new_printer == NULL) {
564 return false;
566 talloc_set_destructor(new_printer, printer_entry_destructor);
568 if (!create_policy_hnd(p, hnd, new_printer)) {
569 TALLOC_FREE(new_printer);
570 return false;
573 /* Add to the internal list. */
574 DLIST_ADD(printers_list, new_printer);
576 new_printer->notify.option=NULL;
578 if (!set_printer_hnd_printertype(new_printer, name)) {
579 close_printer_handle(p, hnd);
580 return false;
583 if (!set_printer_hnd_name(new_printer, name)) {
584 close_printer_handle(p, hnd);
585 return false;
588 new_printer->access_granted = access_granted;
590 DEBUG(5, ("%d printer handles active\n",
591 (int)num_pipe_handles(p->pipe_handles)));
593 return true;
596 /***************************************************************************
597 check to see if the client motify handle is monitoring the notification
598 given by (notify_type, notify_field).
599 **************************************************************************/
601 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
602 uint16_t notify_field)
604 return true;
607 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
608 uint16_t notify_field)
610 struct spoolss_NotifyOption *option = p->notify.option;
611 uint32_t i, j;
614 * Flags should always be zero when the change notify
615 * is registered by the client's spooler. A user Win32 app
616 * might use the flags though instead of the NOTIFY_OPTION_INFO
617 * --jerry
620 if (!option) {
621 return false;
624 if (p->notify.flags)
625 return is_monitoring_event_flags(
626 p->notify.flags, notify_type, notify_field);
628 for (i = 0; i < option->count; i++) {
630 /* Check match for notify_type */
632 if (option->types[i].type != notify_type)
633 continue;
635 /* Check match for field */
637 for (j = 0; j < option->types[i].count; j++) {
638 if (option->types[i].fields[j].field == notify_field) {
639 return true;
644 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
645 p->servername, p->sharename, notify_type, notify_field));
647 return false;
650 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
651 _data->data.integer[0] = _integer; \
652 _data->data.integer[1] = 0;
655 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
656 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
657 if (!_data->data.string.string) {\
658 _data->data.string.size = 0; \
660 _data->data.string.size = strlen_m_term(_p) * 2;
662 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
663 _data->data.devmode.devmode = _devmode;
665 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
666 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
667 if (!_data->data.sd.sd) { \
668 _data->data.sd.sd_size = 0; \
670 _data->data.sd.sd_size = _size;
672 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
673 struct tm *t,
674 const char **pp,
675 uint32_t *plen)
677 struct spoolss_Time st;
678 uint32_t len = 16;
679 char *p;
681 if (!init_systemtime(&st, t)) {
682 return;
685 p = talloc_array(mem_ctx, char, len);
686 if (!p) {
687 return;
691 * Systemtime must be linearized as a set of UINT16's.
692 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
695 SSVAL(p, 0, st.year);
696 SSVAL(p, 2, st.month);
697 SSVAL(p, 4, st.day_of_week);
698 SSVAL(p, 6, st.day);
699 SSVAL(p, 8, st.hour);
700 SSVAL(p, 10, st.minute);
701 SSVAL(p, 12, st.second);
702 SSVAL(p, 14, st.millisecond);
704 *pp = p;
705 *plen = len;
708 /* Convert a notification message to a struct spoolss_Notify */
710 static void notify_one_value(struct spoolss_notify_msg *msg,
711 struct spoolss_Notify *data,
712 TALLOC_CTX *mem_ctx)
714 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
717 static void notify_string(struct spoolss_notify_msg *msg,
718 struct spoolss_Notify *data,
719 TALLOC_CTX *mem_ctx)
721 /* The length of the message includes the trailing \0 */
723 data->data.string.size = msg->len * 2;
724 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
725 if (!data->data.string.string) {
726 data->data.string.size = 0;
727 return;
731 static void notify_system_time(struct spoolss_notify_msg *msg,
732 struct spoolss_Notify *data,
733 TALLOC_CTX *mem_ctx)
735 data->data.string.string = NULL;
736 data->data.string.size = 0;
738 if (msg->len != sizeof(time_t)) {
739 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
740 msg->len));
741 return;
744 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
745 &data->data.string.string,
746 &data->data.string.size);
749 struct notify2_message_table {
750 const char *name;
751 void (*fn)(struct spoolss_notify_msg *msg,
752 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
755 static struct notify2_message_table printer_notify_table[] = {
756 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
757 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
758 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
759 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
760 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
761 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
762 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
763 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
764 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
765 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
766 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
767 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
768 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
769 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
770 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
771 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
772 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
773 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
774 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
777 static struct notify2_message_table job_notify_table[] = {
778 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
779 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
780 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
781 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
782 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
783 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
784 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
785 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
786 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
787 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
788 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
789 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
790 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
791 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
792 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
793 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
794 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
795 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
796 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
797 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
798 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
799 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
800 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
801 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
805 /***********************************************************************
806 Allocate talloc context for container object
807 **********************************************************************/
809 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
811 if ( !ctr )
812 return;
814 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
816 return;
819 /***********************************************************************
820 release all allocated memory and zero out structure
821 **********************************************************************/
823 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
825 if ( !ctr )
826 return;
828 if ( ctr->ctx )
829 talloc_destroy(ctr->ctx);
831 ZERO_STRUCTP(ctr);
833 return;
836 /***********************************************************************
837 **********************************************************************/
839 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
841 if ( !ctr )
842 return NULL;
844 return ctr->ctx;
847 /***********************************************************************
848 **********************************************************************/
850 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
852 if ( !ctr || !ctr->msg_groups )
853 return NULL;
855 if ( idx >= ctr->num_groups )
856 return NULL;
858 return &ctr->msg_groups[idx];
862 /***********************************************************************
863 How many groups of change messages do we have ?
864 **********************************************************************/
866 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
868 if ( !ctr )
869 return 0;
871 return ctr->num_groups;
874 /***********************************************************************
875 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
876 **********************************************************************/
878 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
880 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
881 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
882 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
883 int i, new_slot;
885 if ( !ctr || !msg )
886 return 0;
888 /* loop over all groups looking for a matching printer name */
890 for ( i=0; i<ctr->num_groups; i++ ) {
891 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
892 break;
895 /* add a new group? */
897 if ( i == ctr->num_groups ) {
898 ctr->num_groups++;
900 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
901 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
902 return 0;
904 ctr->msg_groups = groups;
906 /* clear the new entry and set the printer name */
908 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
909 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
912 /* add the change messages; 'i' is the correct index now regardless */
914 msg_grp = &ctr->msg_groups[i];
916 msg_grp->num_msgs++;
918 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
919 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
920 return 0;
922 msg_grp->msgs = msg_list;
924 new_slot = msg_grp->num_msgs-1;
925 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
927 /* need to allocate own copy of data */
929 if ( msg->len != 0 )
930 msg_grp->msgs[new_slot].notify.data = (char *)
931 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
933 return ctr->num_groups;
936 /***********************************************************************
937 Send a change notication message on all handles which have a call
938 back registered
939 **********************************************************************/
941 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
943 Printer_entry *p;
944 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
945 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
946 SPOOLSS_NOTIFY_MSG *messages;
947 int sending_msg_count;
949 if ( !msg_group ) {
950 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
951 return;
954 messages = msg_group->msgs;
956 if ( !messages ) {
957 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
958 return;
961 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
963 /* loop over all printers */
965 for (p = printers_list; p; p = p->next) {
966 struct spoolss_Notify *notifies;
967 uint32_t count = 0;
968 uint32_t id;
969 int i;
971 /* Is there notification on this handle? */
973 if ( !p->notify.client_connected )
974 continue;
976 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
978 /* For this printer? Print servers always receive
979 notifications. */
981 if ( ( p->printer_type == SPLHND_PRINTER ) &&
982 ( !strequal(msg_group->printername, p->sharename) ) )
983 continue;
985 DEBUG(10,("Our printer\n"));
987 /* allocate the max entries possible */
989 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
990 if (!notifies) {
991 return;
994 /* build the array of change notifications */
996 sending_msg_count = 0;
998 for ( i=0; i<msg_group->num_msgs; i++ ) {
999 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1001 /* Are we monitoring this event? */
1003 if (!is_monitoring_event(p, msg->type, msg->field))
1004 continue;
1006 sending_msg_count++;
1009 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1010 msg->type, msg->field, p->sharename));
1013 * if the is a printer notification handle and not a job notification
1014 * type, then set the id to 0. Other wise just use what was specified
1015 * in the message.
1017 * When registering change notification on a print server handle
1018 * we always need to send back the id (snum) matching the printer
1019 * for which the change took place. For change notify registered
1020 * on a printer handle, this does not matter and the id should be 0.
1022 * --jerry
1025 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1026 id = 0;
1027 else
1028 id = msg->id;
1031 /* Convert unix jobid to smb jobid */
1033 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1034 id = sysjob_to_jobid(msg->id);
1036 if (id == -1) {
1037 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1038 goto done;
1042 construct_info_data( &notifies[count], msg->type, msg->field, id );
1044 switch(msg->type) {
1045 case PRINTER_NOTIFY_TYPE:
1046 if ( printer_notify_table[msg->field].fn )
1047 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1048 break;
1050 case JOB_NOTIFY_TYPE:
1051 if ( job_notify_table[msg->field].fn )
1052 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1053 break;
1055 default:
1056 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1057 goto done;
1060 count++;
1063 if ( sending_msg_count ) {
1064 NTSTATUS status;
1065 WERROR werr;
1066 union spoolss_ReplyPrinterInfo info;
1067 struct spoolss_NotifyInfo info0;
1068 uint32_t reply_result;
1070 info0.version = 0x2;
1071 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1072 info0.count = count;
1073 info0.notifies = notifies;
1075 info.info0 = &info0;
1077 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1078 &p->notify.client_hnd,
1079 p->notify.change, /* color */
1080 p->notify.flags,
1081 &reply_result,
1082 0, /* reply_type, must be 0 */
1083 info,
1084 &werr);
1085 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1086 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1087 notify_cli_pipe->srv_name_slash,
1088 win_errstr(werr)));
1090 switch (reply_result) {
1091 case 0:
1092 break;
1093 case PRINTER_NOTIFY_INFO_DISCARDED:
1094 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1095 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1096 break;
1097 default:
1098 break;
1103 done:
1104 DEBUG(8,("send_notify2_changes: Exit...\n"));
1105 return;
1108 /***********************************************************************
1109 **********************************************************************/
1111 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1114 uint32_t tv_sec, tv_usec;
1115 size_t offset = 0;
1117 /* Unpack message */
1119 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1120 msg->printer);
1122 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1123 &tv_sec, &tv_usec,
1124 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1126 if (msg->len == 0)
1127 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1128 &msg->notify.value[0], &msg->notify.value[1]);
1129 else
1130 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1131 &msg->len, &msg->notify.data);
1133 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1134 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1136 tv->tv_sec = tv_sec;
1137 tv->tv_usec = tv_usec;
1139 if (msg->len == 0)
1140 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1141 msg->notify.value[1]));
1142 else
1143 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1145 return true;
1148 /********************************************************************
1149 Receive a notify2 message list
1150 ********************************************************************/
1152 static void receive_notify2_message_list(struct messaging_context *msg,
1153 void *private_data,
1154 uint32_t msg_type,
1155 struct server_id server_id,
1156 DATA_BLOB *data)
1158 size_t msg_count, i;
1159 char *buf = (char *)data->data;
1160 char *msg_ptr;
1161 size_t msg_len;
1162 SPOOLSS_NOTIFY_MSG notify;
1163 SPOOLSS_NOTIFY_MSG_CTR messages;
1164 int num_groups;
1166 if (data->length < 4) {
1167 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1168 return;
1171 msg_count = IVAL(buf, 0);
1172 msg_ptr = buf + 4;
1174 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1176 if (msg_count == 0) {
1177 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1178 return;
1181 /* initialize the container */
1183 ZERO_STRUCT( messages );
1184 notify_msg_ctr_init( &messages );
1187 * build message groups for each printer identified
1188 * in a change_notify msg. Remember that a PCN message
1189 * includes the handle returned for the srv_spoolss_replyopenprinter()
1190 * call. Therefore messages are grouped according to printer handle.
1193 for ( i=0; i<msg_count; i++ ) {
1194 struct timeval msg_tv;
1196 if (msg_ptr + 4 - buf > data->length) {
1197 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1198 return;
1201 msg_len = IVAL(msg_ptr,0);
1202 msg_ptr += 4;
1204 if (msg_ptr + msg_len - buf > data->length) {
1205 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1206 return;
1209 /* unpack messages */
1211 ZERO_STRUCT( notify );
1212 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1213 msg_ptr += msg_len;
1215 /* add to correct list in container */
1217 notify_msg_ctr_addmsg( &messages, &notify );
1219 /* free memory that might have been allocated by notify2_unpack_msg() */
1221 if ( notify.len != 0 )
1222 SAFE_FREE( notify.notify.data );
1225 /* process each group of messages */
1227 num_groups = notify_msg_ctr_numgroups( &messages );
1228 for ( i=0; i<num_groups; i++ )
1229 send_notify2_changes( &messages, i );
1232 /* cleanup */
1234 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1235 (uint32_t)msg_count ));
1237 notify_msg_ctr_destroy( &messages );
1239 return;
1242 /********************************************************************
1243 Send a message to ourself about new driver being installed
1244 so we can upgrade the information for each printer bound to this
1245 driver
1246 ********************************************************************/
1248 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1250 int len = strlen(drivername);
1252 if (!len)
1253 return false;
1255 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1256 drivername));
1258 messaging_send_buf(smbd_messaging_context(), procid_self(),
1259 MSG_PRINTER_DRVUPGRADE,
1260 (uint8_t *)drivername, len+1);
1262 return true;
1265 /**********************************************************************
1266 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1267 over all printers, upgrading ones as necessary
1268 **********************************************************************/
1270 void do_drv_upgrade_printer(struct messaging_context *msg,
1271 void *private_data,
1272 uint32_t msg_type,
1273 struct server_id server_id,
1274 DATA_BLOB *data)
1276 fstring drivername;
1277 int snum;
1278 int n_services = lp_numservices();
1279 size_t len;
1281 len = MIN(data->length,sizeof(drivername)-1);
1282 strncpy(drivername, (const char *)data->data, len);
1284 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1286 /* Iterate the printer list */
1288 for (snum=0; snum<n_services; snum++)
1290 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1292 WERROR result;
1293 NT_PRINTER_INFO_LEVEL *printer = NULL;
1295 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1296 if (!W_ERROR_IS_OK(result))
1297 continue;
1299 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1301 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1303 /* all we care about currently is the change_id */
1305 result = mod_a_printer(printer, 2);
1306 if (!W_ERROR_IS_OK(result)) {
1307 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1308 win_errstr(result)));
1312 free_a_printer(&printer, 2);
1316 /* all done */
1319 /********************************************************************
1320 Update the cache for all printq's with a registered client
1321 connection
1322 ********************************************************************/
1324 void update_monitored_printq_cache( void )
1326 Printer_entry *printer = printers_list;
1327 int snum;
1329 /* loop through all printers and update the cache where
1330 client_connected == true */
1331 while ( printer )
1333 if ( (printer->printer_type == SPLHND_PRINTER)
1334 && printer->notify.client_connected )
1336 snum = print_queue_snum(printer->sharename);
1337 print_queue_status( snum, NULL, NULL );
1340 printer = printer->next;
1343 return;
1345 /********************************************************************
1346 Send a message to ourself about new driver being installed
1347 so we can upgrade the information for each printer bound to this
1348 driver
1349 ********************************************************************/
1351 static bool srv_spoolss_reset_printerdata(char* drivername)
1353 int len = strlen(drivername);
1355 if (!len)
1356 return false;
1358 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1359 drivername));
1361 messaging_send_buf(smbd_messaging_context(), procid_self(),
1362 MSG_PRINTERDATA_INIT_RESET,
1363 (uint8_t *)drivername, len+1);
1365 return true;
1368 /**********************************************************************
1369 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1370 over all printers, resetting printer data as neessary
1371 **********************************************************************/
1373 void reset_all_printerdata(struct messaging_context *msg,
1374 void *private_data,
1375 uint32_t msg_type,
1376 struct server_id server_id,
1377 DATA_BLOB *data)
1379 fstring drivername;
1380 int snum;
1381 int n_services = lp_numservices();
1382 size_t len;
1384 len = MIN( data->length, sizeof(drivername)-1 );
1385 strncpy( drivername, (const char *)data->data, len );
1387 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1389 /* Iterate the printer list */
1391 for ( snum=0; snum<n_services; snum++ )
1393 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1395 WERROR result;
1396 NT_PRINTER_INFO_LEVEL *printer = NULL;
1398 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1399 if ( !W_ERROR_IS_OK(result) )
1400 continue;
1403 * if the printer is bound to the driver,
1404 * then reset to the new driver initdata
1407 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1409 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1411 if ( !set_driver_init(printer, 2) ) {
1412 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1413 printer->info_2->printername, printer->info_2->drivername));
1416 result = mod_a_printer( printer, 2 );
1417 if ( !W_ERROR_IS_OK(result) ) {
1418 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1419 get_dos_error_msg(result)));
1423 free_a_printer( &printer, 2 );
1427 /* all done */
1429 return;
1432 /****************************************************************
1433 _spoolss_OpenPrinter
1434 ****************************************************************/
1436 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1437 struct spoolss_OpenPrinter *r)
1439 struct spoolss_OpenPrinterEx e;
1440 WERROR werr;
1442 ZERO_STRUCT(e.in.userlevel);
1444 e.in.printername = r->in.printername;
1445 e.in.datatype = r->in.datatype;
1446 e.in.devmode_ctr = r->in.devmode_ctr;
1447 e.in.access_mask = r->in.access_mask;
1448 e.in.level = 0;
1450 e.out.handle = r->out.handle;
1452 werr = _spoolss_OpenPrinterEx(p, &e);
1454 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1455 /* OpenPrinterEx returns this for a bad
1456 * printer name. We must return WERR_INVALID_PRINTER_NAME
1457 * instead.
1459 werr = WERR_INVALID_PRINTER_NAME;
1462 return werr;
1465 /********************************************************************
1466 ********************************************************************/
1468 bool convert_devicemode(const char *printername,
1469 const struct spoolss_DeviceMode *devmode,
1470 NT_DEVICEMODE **pp_nt_devmode)
1472 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1475 * Ensure nt_devmode is a valid pointer
1476 * as we will be overwriting it.
1479 if (nt_devmode == NULL) {
1480 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1481 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1482 return false;
1485 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1486 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1488 nt_devmode->specversion = devmode->specversion;
1489 nt_devmode->driverversion = devmode->driverversion;
1490 nt_devmode->size = devmode->size;
1491 nt_devmode->fields = devmode->fields;
1492 nt_devmode->orientation = devmode->orientation;
1493 nt_devmode->papersize = devmode->papersize;
1494 nt_devmode->paperlength = devmode->paperlength;
1495 nt_devmode->paperwidth = devmode->paperwidth;
1496 nt_devmode->scale = devmode->scale;
1497 nt_devmode->copies = devmode->copies;
1498 nt_devmode->defaultsource = devmode->defaultsource;
1499 nt_devmode->printquality = devmode->printquality;
1500 nt_devmode->color = devmode->color;
1501 nt_devmode->duplex = devmode->duplex;
1502 nt_devmode->yresolution = devmode->yresolution;
1503 nt_devmode->ttoption = devmode->ttoption;
1504 nt_devmode->collate = devmode->collate;
1506 nt_devmode->logpixels = devmode->logpixels;
1507 nt_devmode->bitsperpel = devmode->bitsperpel;
1508 nt_devmode->pelswidth = devmode->pelswidth;
1509 nt_devmode->pelsheight = devmode->pelsheight;
1510 nt_devmode->displayflags = devmode->displayflags;
1511 nt_devmode->displayfrequency = devmode->displayfrequency;
1512 nt_devmode->icmmethod = devmode->icmmethod;
1513 nt_devmode->icmintent = devmode->icmintent;
1514 nt_devmode->mediatype = devmode->mediatype;
1515 nt_devmode->dithertype = devmode->dithertype;
1516 nt_devmode->reserved1 = devmode->reserved1;
1517 nt_devmode->reserved2 = devmode->reserved2;
1518 nt_devmode->panningwidth = devmode->panningwidth;
1519 nt_devmode->panningheight = devmode->panningheight;
1522 * Only change private and driverextra if the incoming devmode
1523 * has a new one. JRA.
1526 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1527 SAFE_FREE(nt_devmode->nt_dev_private);
1528 nt_devmode->driverextra = devmode->__driverextra_length;
1529 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1530 return false;
1531 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1534 *pp_nt_devmode = nt_devmode;
1536 return true;
1539 /****************************************************************
1540 _spoolss_OpenPrinterEx
1541 ****************************************************************/
1543 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1544 struct spoolss_OpenPrinterEx *r)
1546 int snum;
1547 Printer_entry *Printer=NULL;
1549 if (!r->in.printername) {
1550 return WERR_INVALID_PARAM;
1553 /* some sanity check because you can open a printer or a print server */
1554 /* aka: \\server\printer or \\server */
1556 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1558 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1559 ZERO_STRUCTP(r->out.handle);
1560 return WERR_INVALID_PARAM;
1563 Printer = find_printer_index_by_hnd(p, r->out.handle);
1564 if ( !Printer ) {
1565 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1566 "handle we created for printer %s\n", r->in.printername));
1567 close_printer_handle(p, r->out.handle);
1568 ZERO_STRUCTP(r->out.handle);
1569 return WERR_INVALID_PARAM;
1573 * First case: the user is opening the print server:
1575 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1576 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1578 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1579 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1580 * or if the user is listed in the smb.conf printer admin parameter.
1582 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1583 * client view printer folder, but does not show the MSAPW.
1585 * Note: this test needs code to check access rights here too. Jeremy
1586 * could you look at this?
1588 * Second case: the user is opening a printer:
1589 * NT doesn't let us connect to a printer if the connecting user
1590 * doesn't have print permission.
1592 * Third case: user is opening a Port Monitor
1593 * access checks same as opening a handle to the print server.
1596 switch (Printer->printer_type )
1598 case SPLHND_SERVER:
1599 case SPLHND_PORTMON_TCP:
1600 case SPLHND_PORTMON_LOCAL:
1601 /* Printserver handles use global struct... */
1603 snum = -1;
1605 /* Map standard access rights to object specific access rights */
1607 se_map_standard(&r->in.access_mask,
1608 &printserver_std_mapping);
1610 /* Deny any object specific bits that don't apply to print
1611 servers (i.e printer and job specific bits) */
1613 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1615 if (r->in.access_mask &
1616 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1617 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1618 close_printer_handle(p, r->out.handle);
1619 ZERO_STRUCTP(r->out.handle);
1620 return WERR_ACCESS_DENIED;
1623 /* Allow admin access */
1625 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1627 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1629 if (!lp_ms_add_printer_wizard()) {
1630 close_printer_handle(p, r->out.handle);
1631 ZERO_STRUCTP(r->out.handle);
1632 return WERR_ACCESS_DENIED;
1635 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1636 and not a printer admin, then fail */
1638 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1639 !user_has_privileges(p->server_info->ptok,
1640 &se_printop ) &&
1641 !token_contains_name_in_list(
1642 uidtoname(p->server_info->utok.uid),
1643 NULL, NULL,
1644 p->server_info->ptok,
1645 lp_printer_admin(snum))) {
1646 close_printer_handle(p, r->out.handle);
1647 ZERO_STRUCTP(r->out.handle);
1648 return WERR_ACCESS_DENIED;
1651 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1653 else
1655 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1658 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1659 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1661 /* We fall through to return WERR_OK */
1662 break;
1664 case SPLHND_PRINTER:
1665 /* NT doesn't let us connect to a printer if the connecting user
1666 doesn't have print permission. */
1668 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1669 close_printer_handle(p, r->out.handle);
1670 ZERO_STRUCTP(r->out.handle);
1671 return WERR_BADFID;
1674 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1676 /* map an empty access mask to the minimum access mask */
1677 if (r->in.access_mask == 0x0)
1678 r->in.access_mask = PRINTER_ACCESS_USE;
1681 * If we are not serving the printer driver for this printer,
1682 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1683 * will keep NT clients happy --jerry
1686 if (lp_use_client_driver(snum)
1687 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1689 r->in.access_mask = PRINTER_ACCESS_USE;
1692 /* check smb.conf parameters and the the sec_desc */
1694 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1695 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1696 ZERO_STRUCTP(r->out.handle);
1697 return WERR_ACCESS_DENIED;
1700 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1701 p->server_info->ptok, snum) ||
1702 !print_access_check(p->server_info, snum,
1703 r->in.access_mask)) {
1704 DEBUG(3, ("access DENIED for printer open\n"));
1705 close_printer_handle(p, r->out.handle);
1706 ZERO_STRUCTP(r->out.handle);
1707 return WERR_ACCESS_DENIED;
1710 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1711 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1712 close_printer_handle(p, r->out.handle);
1713 ZERO_STRUCTP(r->out.handle);
1714 return WERR_ACCESS_DENIED;
1717 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1718 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1719 else
1720 r->in.access_mask = PRINTER_ACCESS_USE;
1722 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1723 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1725 break;
1727 default:
1728 /* sanity check to prevent programmer error */
1729 ZERO_STRUCTP(r->out.handle);
1730 return WERR_BADFID;
1733 Printer->access_granted = r->in.access_mask;
1736 * If the client sent a devmode in the OpenPrinter() call, then
1737 * save it here in case we get a job submission on this handle
1740 if ((Printer->printer_type != SPLHND_SERVER) &&
1741 r->in.devmode_ctr.devmode) {
1742 convert_devicemode(Printer->sharename,
1743 r->in.devmode_ctr.devmode,
1744 &Printer->nt_devmode);
1747 #if 0 /* JERRY -- I'm doubtful this is really effective */
1748 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1749 optimization in Windows 2000 clients --jerry */
1751 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1752 && (RA_WIN2K == get_remote_arch()) )
1754 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1755 sys_usleep( 500000 );
1757 #endif
1759 return WERR_OK;
1762 /****************************************************************************
1763 ****************************************************************************/
1765 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1766 NT_PRINTER_INFO_LEVEL_2 *d)
1768 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1770 if (!r || !d) {
1771 return false;
1774 d->attributes = r->attributes;
1775 d->priority = r->priority;
1776 d->default_priority = r->defaultpriority;
1777 d->starttime = r->starttime;
1778 d->untiltime = r->untiltime;
1779 d->status = r->status;
1780 d->cjobs = r->cjobs;
1782 fstrcpy(d->servername, r->servername);
1783 fstrcpy(d->printername, r->printername);
1784 fstrcpy(d->sharename, r->sharename);
1785 fstrcpy(d->portname, r->portname);
1786 fstrcpy(d->drivername, r->drivername);
1787 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1788 fstrcpy(d->location, r->location);
1789 fstrcpy(d->sepfile, r->sepfile);
1790 fstrcpy(d->printprocessor, r->printprocessor);
1791 fstrcpy(d->datatype, r->datatype);
1792 fstrcpy(d->parameters, r->parameters);
1794 return true;
1797 /****************************************************************************
1798 ****************************************************************************/
1800 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1801 NT_PRINTER_INFO_LEVEL *printer)
1803 bool ret;
1805 switch (info_ctr->level) {
1806 case 2:
1807 /* allocate memory if needed. Messy because
1808 convert_printer_info is used to update an existing
1809 printer or build a new one */
1811 if (!printer->info_2) {
1812 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1813 if (!printer->info_2) {
1814 DEBUG(0,("convert_printer_info: "
1815 "talloc() failed!\n"));
1816 return false;
1820 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1821 printer->info_2);
1822 printer->info_2->setuptime = time(NULL);
1823 return ret;
1826 return false;
1829 /*******************************************************************
1830 ********************************************************************/
1832 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1834 int i;
1836 if (!sarray) {
1837 *farray = NULL;
1838 return true;
1841 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1842 if (!*farray) {
1843 return false;
1846 for (i=0; sarray[i] != NULL; i++) {
1847 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1848 if (!*farray) {
1849 return false;
1851 fstrcpy((*farray)[i], sarray[i]);
1854 fstrcpy((*farray)[i], "");
1856 return true;
1859 /*******************************************************************
1860 ********************************************************************/
1862 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1863 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1865 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1867 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1869 if (*p == NULL) {
1870 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1871 if (*p == NULL) {
1872 return false;
1874 ZERO_STRUCTP(*p);
1877 d = *p;
1879 d->cversion = r->version;
1881 fstrcpy(d->name, r->driver_name);
1882 fstrcpy(d->environment, r->architecture);
1883 fstrcpy(d->driverpath, r->driver_path);
1884 fstrcpy(d->datafile, r->data_file);
1885 fstrcpy(d->configfile, r->config_file);
1886 fstrcpy(d->helpfile, r->help_file);
1887 fstrcpy(d->monitorname, r->monitor_name);
1888 fstrcpy(d->defaultdatatype, r->default_datatype);
1890 DEBUGADD(8,( "version: %d\n", d->cversion));
1891 DEBUGADD(8,( "name: %s\n", d->name));
1892 DEBUGADD(8,( "environment: %s\n", d->environment));
1893 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1894 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1895 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1896 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1897 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1898 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1900 if (r->dependent_files) {
1901 if (!string_array_to_fstring_array(r->dependent_files->string,
1902 &d->dependentfiles)) {
1903 SAFE_FREE(*p);
1904 return false;
1908 return true;
1911 /*******************************************************************
1912 ********************************************************************/
1914 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1915 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1917 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1919 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1921 if (*p == NULL) {
1922 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1923 if (*p == NULL) {
1924 return false;
1926 ZERO_STRUCTP(*p);
1929 d = *p;
1931 d->version = r->version;
1933 fstrcpy(d->name, r->driver_name);
1934 fstrcpy(d->environment, r->architecture);
1935 fstrcpy(d->driverpath, r->driver_path);
1936 fstrcpy(d->datafile, r->data_file);
1937 fstrcpy(d->configfile, r->config_file);
1938 fstrcpy(d->helpfile, r->help_file);
1939 fstrcpy(d->monitorname, r->monitor_name);
1940 fstrcpy(d->defaultdatatype, r->default_datatype);
1942 DEBUGADD(8,( "version: %d\n", d->version));
1943 DEBUGADD(8,( "name: %s\n", d->name));
1944 DEBUGADD(8,( "environment: %s\n", d->environment));
1945 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1946 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1947 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1948 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1949 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1950 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1952 if (r->dependent_files) {
1953 if (!string_array_to_fstring_array(r->dependent_files->string,
1954 &d->dependentfiles)) {
1955 goto error;
1959 if (r->previous_names) {
1960 if (!string_array_to_fstring_array(r->previous_names->string,
1961 &d->previousnames)) {
1962 goto error;
1966 return true;
1968 error:
1969 SAFE_FREE(*p);
1970 return false;
1973 /********************************************************************
1974 ********************************************************************/
1976 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1977 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1978 uint32_t level)
1980 switch (level) {
1981 case 3:
1982 printer->info_3 = NULL;
1983 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1984 return false;
1986 break;
1987 case 6:
1988 printer->info_6 = NULL;
1989 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1990 return false;
1992 break;
1993 default:
1994 return false;
1997 return true;
2000 /****************************************************************
2001 _spoolss_ClosePrinter
2002 ****************************************************************/
2004 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2005 struct spoolss_ClosePrinter *r)
2007 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2009 if (Printer && Printer->document_started) {
2010 struct spoolss_EndDocPrinter e;
2012 e.in.handle = r->in.handle;
2014 _spoolss_EndDocPrinter(p, &e);
2017 if (!close_printer_handle(p, r->in.handle))
2018 return WERR_BADFID;
2020 /* clear the returned printer handle. Observed behavior
2021 from Win2k server. Don't think this really matters.
2022 Previous code just copied the value of the closed
2023 handle. --jerry */
2025 ZERO_STRUCTP(r->out.handle);
2027 return WERR_OK;
2030 /****************************************************************
2031 _spoolss_DeletePrinter
2032 ****************************************************************/
2034 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2035 struct spoolss_DeletePrinter *r)
2037 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2038 WERROR result;
2040 if (Printer && Printer->document_started) {
2041 struct spoolss_EndDocPrinter e;
2043 e.in.handle = r->in.handle;
2045 _spoolss_EndDocPrinter(p, &e);
2048 result = delete_printer_handle(p, r->in.handle);
2050 update_c_setprinter(false);
2052 return result;
2055 /*******************************************************************
2056 * static function to lookup the version id corresponding to an
2057 * long architecture string
2058 ******************************************************************/
2060 static int get_version_id(const char *arch)
2062 int i;
2063 struct print_architecture_table_node archi_table[]= {
2065 {"Windows 4.0", "WIN40", 0 },
2066 {"Windows NT x86", "W32X86", 2 },
2067 {"Windows NT R4000", "W32MIPS", 2 },
2068 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2069 {"Windows NT PowerPC", "W32PPC", 2 },
2070 {"Windows IA64", "IA64", 3 },
2071 {"Windows x64", "x64", 3 },
2072 {NULL, "", -1 }
2075 for (i=0; archi_table[i].long_archi != NULL; i++)
2077 if (strcmp(arch, archi_table[i].long_archi) == 0)
2078 return (archi_table[i].version);
2081 return -1;
2084 /****************************************************************
2085 _spoolss_DeletePrinterDriver
2086 ****************************************************************/
2088 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2089 struct spoolss_DeletePrinterDriver *r)
2091 NT_PRINTER_DRIVER_INFO_LEVEL info;
2092 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2093 int version;
2094 WERROR status;
2095 WERROR status_win2k = WERR_ACCESS_DENIED;
2096 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2098 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2099 and not a printer admin, then fail */
2101 if ( (p->server_info->utok.uid != sec_initial_uid())
2102 && !user_has_privileges(p->server_info->ptok, &se_printop )
2103 && !token_contains_name_in_list(
2104 uidtoname(p->server_info->utok.uid), NULL,
2105 NULL, p->server_info->ptok,
2106 lp_printer_admin(-1)) )
2108 return WERR_ACCESS_DENIED;
2111 /* check that we have a valid driver name first */
2113 if ((version = get_version_id(r->in.architecture)) == -1)
2114 return WERR_INVALID_ENVIRONMENT;
2116 ZERO_STRUCT(info);
2117 ZERO_STRUCT(info_win2k);
2119 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2120 r->in.architecture,
2121 version)))
2123 /* try for Win2k driver if "Windows NT x86" */
2125 if ( version == 2 ) {
2126 version = 3;
2127 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2128 r->in.driver,
2129 r->in.architecture,
2130 version))) {
2131 status = WERR_UNKNOWN_PRINTER_DRIVER;
2132 goto done;
2135 /* otherwise it was a failure */
2136 else {
2137 status = WERR_UNKNOWN_PRINTER_DRIVER;
2138 goto done;
2143 if (printer_driver_in_use(info.info_3)) {
2144 status = WERR_PRINTER_DRIVER_IN_USE;
2145 goto done;
2148 if ( version == 2 )
2150 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2151 r->in.driver,
2152 r->in.architecture, 3)))
2154 /* if we get to here, we now have 2 driver info structures to remove */
2155 /* remove the Win2k driver first*/
2157 status_win2k = delete_printer_driver(
2158 p, info_win2k.info_3, 3, false);
2159 free_a_printer_driver( info_win2k, 3 );
2161 /* this should not have failed---if it did, report to client */
2162 if ( !W_ERROR_IS_OK(status_win2k) )
2164 status = status_win2k;
2165 goto done;
2170 status = delete_printer_driver(p, info.info_3, version, false);
2172 /* if at least one of the deletes succeeded return OK */
2174 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2175 status = WERR_OK;
2177 done:
2178 free_a_printer_driver( info, 3 );
2180 return status;
2183 /****************************************************************
2184 _spoolss_DeletePrinterDriverEx
2185 ****************************************************************/
2187 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2188 struct spoolss_DeletePrinterDriverEx *r)
2190 NT_PRINTER_DRIVER_INFO_LEVEL info;
2191 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2192 int version;
2193 bool delete_files;
2194 WERROR status;
2195 WERROR status_win2k = WERR_ACCESS_DENIED;
2196 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2198 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2199 and not a printer admin, then fail */
2201 if ( (p->server_info->utok.uid != sec_initial_uid())
2202 && !user_has_privileges(p->server_info->ptok, &se_printop )
2203 && !token_contains_name_in_list(
2204 uidtoname(p->server_info->utok.uid), NULL, NULL,
2205 p->server_info->ptok, lp_printer_admin(-1)) )
2207 return WERR_ACCESS_DENIED;
2210 /* check that we have a valid driver name first */
2211 if ((version = get_version_id(r->in.architecture)) == -1) {
2212 /* this is what NT returns */
2213 return WERR_INVALID_ENVIRONMENT;
2216 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2217 version = r->in.version;
2219 ZERO_STRUCT(info);
2220 ZERO_STRUCT(info_win2k);
2222 status = get_a_printer_driver(&info, 3, r->in.driver,
2223 r->in.architecture, version);
2225 if ( !W_ERROR_IS_OK(status) )
2228 * if the client asked for a specific version,
2229 * or this is something other than Windows NT x86,
2230 * then we've failed
2233 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2234 goto done;
2236 /* try for Win2k driver if "Windows NT x86" */
2238 version = 3;
2239 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2240 r->in.architecture,
2241 version))) {
2242 status = WERR_UNKNOWN_PRINTER_DRIVER;
2243 goto done;
2247 if ( printer_driver_in_use(info.info_3) ) {
2248 status = WERR_PRINTER_DRIVER_IN_USE;
2249 goto done;
2253 * we have a couple of cases to consider.
2254 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2255 * then the delete should fail if **any** files overlap with
2256 * other drivers
2257 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2258 * non-overlapping files
2259 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2260 * is set, the do not delete any files
2261 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2264 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2266 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2268 if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2269 /* no idea of the correct error here */
2270 status = WERR_ACCESS_DENIED;
2271 goto done;
2275 /* also check for W32X86/3 if necessary; maybe we already have? */
2277 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2278 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2279 r->in.driver,
2280 r->in.architecture, 3)))
2283 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2284 /* no idea of the correct error here */
2285 free_a_printer_driver( info_win2k, 3 );
2286 status = WERR_ACCESS_DENIED;
2287 goto done;
2290 /* if we get to here, we now have 2 driver info structures to remove */
2291 /* remove the Win2k driver first*/
2293 status_win2k = delete_printer_driver(
2294 p, info_win2k.info_3, 3, delete_files);
2295 free_a_printer_driver( info_win2k, 3 );
2297 /* this should not have failed---if it did, report to client */
2299 if ( !W_ERROR_IS_OK(status_win2k) )
2300 goto done;
2304 status = delete_printer_driver(p, info.info_3, version, delete_files);
2306 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2307 status = WERR_OK;
2308 done:
2309 free_a_printer_driver( info, 3 );
2311 return status;
2315 /****************************************************************************
2316 Internal routine for removing printerdata
2317 ***************************************************************************/
2319 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2321 return delete_printer_data( printer->info_2, key, value );
2324 /****************************************************************************
2325 Internal routine for storing printerdata
2326 ***************************************************************************/
2328 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2329 const char *key, const char *value,
2330 uint32_t type, uint8_t *data, int real_len)
2332 /* the registry objects enforce uniqueness based on value name */
2334 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2337 /********************************************************************
2338 GetPrinterData on a printer server Handle.
2339 ********************************************************************/
2341 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2342 const char *value,
2343 enum winreg_Type *type,
2344 union spoolss_PrinterData *data)
2346 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2348 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2349 *type = REG_DWORD;
2350 data->value = 0x00;
2351 return WERR_OK;
2354 if (!StrCaseCmp(value, "BeepEnabled")) {
2355 *type = REG_DWORD;
2356 data->value = 0x00;
2357 return WERR_OK;
2360 if (!StrCaseCmp(value, "EventLog")) {
2361 *type = REG_DWORD;
2362 /* formally was 0x1b */
2363 data->value = 0x00;
2364 return WERR_OK;
2367 if (!StrCaseCmp(value, "NetPopup")) {
2368 *type = REG_DWORD;
2369 data->value = 0x00;
2370 return WERR_OK;
2373 if (!StrCaseCmp(value, "MajorVersion")) {
2374 *type = REG_DWORD;
2376 /* Windows NT 4.0 seems to not allow uploading of drivers
2377 to a server that reports 0x3 as the MajorVersion.
2378 need to investigate more how Win2k gets around this .
2379 -- jerry */
2381 if (RA_WINNT == get_remote_arch()) {
2382 data->value = 0x02;
2383 } else {
2384 data->value = 0x03;
2387 return WERR_OK;
2390 if (!StrCaseCmp(value, "MinorVersion")) {
2391 *type = REG_DWORD;
2392 data->value = 0x00;
2393 return WERR_OK;
2396 /* REG_BINARY
2397 * uint32_t size = 0x114
2398 * uint32_t major = 5
2399 * uint32_t minor = [0|1]
2400 * uint32_t build = [2195|2600]
2401 * extra unicode string = e.g. "Service Pack 3"
2403 if (!StrCaseCmp(value, "OSVersion")) {
2404 DATA_BLOB blob;
2405 enum ndr_err_code ndr_err;
2406 struct spoolss_OSVersion os;
2408 os.major = 5; /* Windows 2000 == 5.0 */
2409 os.minor = 0;
2410 os.build = 2195; /* build */
2411 os.extra_string = ""; /* leave extra string empty */
2413 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2414 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2415 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2416 return WERR_GENERAL_FAILURE;
2419 *type = REG_BINARY;
2420 data->binary = blob;
2422 return WERR_OK;
2426 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2427 *type = REG_SZ;
2429 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2430 W_ERROR_HAVE_NO_MEMORY(data->string);
2432 return WERR_OK;
2435 if (!StrCaseCmp(value, "Architecture")) {
2436 *type = REG_SZ;
2438 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2439 W_ERROR_HAVE_NO_MEMORY(data->string);
2441 return WERR_OK;
2444 if (!StrCaseCmp(value, "DsPresent")) {
2445 *type = REG_DWORD;
2447 /* only show the publish check box if we are a
2448 member of a AD domain */
2450 if (lp_security() == SEC_ADS) {
2451 data->value = 0x01;
2452 } else {
2453 data->value = 0x00;
2455 return WERR_OK;
2458 if (!StrCaseCmp(value, "DNSMachineName")) {
2459 const char *hostname = get_mydnsfullname();
2461 if (!hostname) {
2462 return WERR_BADFILE;
2465 *type = REG_SZ;
2466 data->string = talloc_strdup(mem_ctx, hostname);
2467 W_ERROR_HAVE_NO_MEMORY(data->string);
2469 return WERR_OK;
2472 return WERR_INVALID_PARAM;
2475 /****************************************************************
2476 _spoolss_GetPrinterData
2477 ****************************************************************/
2479 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2480 struct spoolss_GetPrinterData *r)
2482 WERROR result;
2483 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2484 NT_PRINTER_INFO_LEVEL *printer = NULL;
2485 int snum = 0;
2488 * Reminder: when it's a string, the length is in BYTES
2489 * even if UNICODE is negociated.
2491 * JFM, 4/19/1999
2494 /* in case of problem, return some default values */
2496 *r->out.needed = 0;
2497 *r->out.type = 0;
2499 DEBUG(4,("_spoolss_GetPrinterData\n"));
2501 if (!Printer) {
2502 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2503 OUR_HANDLE(r->in.handle)));
2504 result = WERR_BADFID;
2505 goto done;
2508 if (Printer->printer_type == SPLHND_SERVER) {
2509 result = getprinterdata_printer_server(p->mem_ctx,
2510 r->in.value_name,
2511 r->out.type,
2512 r->out.data);
2513 } else {
2514 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2515 result = WERR_BADFID;
2516 goto done;
2519 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2520 if (!W_ERROR_IS_OK(result)) {
2521 goto done;
2524 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2526 if (strequal(r->in.value_name, "ChangeId")) {
2527 *r->out.type = REG_DWORD;
2528 r->out.data->value = printer->info_2->changeid;
2529 result = WERR_OK;
2530 } else {
2531 struct regval_blob *v;
2532 DATA_BLOB blob;
2534 v = get_printer_data(printer->info_2,
2535 SPOOL_PRINTERDATA_KEY,
2536 r->in.value_name);
2537 if (!v) {
2538 result = WERR_BADFILE;
2539 goto done;
2542 *r->out.type = v->type;
2544 blob = data_blob_const(v->data_p, v->size);
2546 result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2547 r->out.data,
2548 *r->out.type);
2552 done:
2553 /* cleanup & exit */
2555 if (printer) {
2556 free_a_printer(&printer, 2);
2559 if (!W_ERROR_IS_OK(result)) {
2560 return result;
2563 *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2564 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2565 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2567 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2570 /*********************************************************
2571 Connect to the client machine.
2572 **********************************************************/
2574 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2575 struct sockaddr_storage *client_ss, const char *remote_machine)
2577 NTSTATUS ret;
2578 struct cli_state *the_cli;
2579 struct sockaddr_storage rm_addr;
2581 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2582 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2583 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2584 return false;
2587 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2588 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2589 return false;
2591 } else {
2592 char addr[INET6_ADDRSTRLEN];
2593 rm_addr = *client_ss;
2594 print_sockaddr(addr, sizeof(addr), &rm_addr);
2595 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2596 addr));
2599 /* setup the connection */
2601 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2602 &rm_addr, 0, "IPC$", "IPC",
2603 "", /* username */
2604 "", /* domain */
2605 "", /* password */
2606 0, lp_client_signing(), NULL );
2608 if ( !NT_STATUS_IS_OK( ret ) ) {
2609 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2610 remote_machine ));
2611 return false;
2614 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2615 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2616 cli_shutdown(the_cli);
2617 return false;
2621 * Ok - we have an anonymous connection to the IPC$ share.
2622 * Now start the NT Domain stuff :-).
2625 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2626 if (!NT_STATUS_IS_OK(ret)) {
2627 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2628 remote_machine, nt_errstr(ret)));
2629 cli_shutdown(the_cli);
2630 return false;
2633 return true;
2636 /***************************************************************************
2637 Connect to the client.
2638 ****************************************************************************/
2640 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2641 uint32_t localprinter, uint32_t type,
2642 struct policy_handle *handle,
2643 struct sockaddr_storage *client_ss)
2645 WERROR result;
2646 NTSTATUS status;
2649 * If it's the first connection, contact the client
2650 * and connect to the IPC$ share anonymously
2652 if (smb_connections==0) {
2653 fstring unix_printer;
2655 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2657 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2658 return false;
2660 messaging_register(smbd_messaging_context(), NULL,
2661 MSG_PRINTER_NOTIFY2,
2662 receive_notify2_message_list);
2663 /* Tell the connections db we're now interested in printer
2664 * notify messages. */
2665 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2669 * Tell the specific printing tdb we want messages for this printer
2670 * by registering our PID.
2673 if (!print_notify_register_pid(snum))
2674 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2676 smb_connections++;
2678 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2679 printer,
2680 localprinter,
2681 type,
2683 NULL,
2684 handle,
2685 &result);
2686 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2687 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2688 win_errstr(result)));
2690 return (W_ERROR_IS_OK(result));
2693 /****************************************************************
2694 ****************************************************************/
2696 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2697 const struct spoolss_NotifyOption *r)
2699 struct spoolss_NotifyOption *option;
2700 uint32_t i,k;
2702 if (!r) {
2703 return NULL;
2706 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2707 if (!option) {
2708 return NULL;
2711 *option = *r;
2713 if (!option->count) {
2714 return option;
2717 option->types = talloc_zero_array(option,
2718 struct spoolss_NotifyOptionType, option->count);
2719 if (!option->types) {
2720 talloc_free(option);
2721 return NULL;
2724 for (i=0; i < option->count; i++) {
2725 option->types[i] = r->types[i];
2727 if (option->types[i].count) {
2728 option->types[i].fields = talloc_zero_array(option,
2729 union spoolss_Field, option->types[i].count);
2730 if (!option->types[i].fields) {
2731 talloc_free(option);
2732 return NULL;
2734 for (k=0; k<option->types[i].count; k++) {
2735 option->types[i].fields[k] =
2736 r->types[i].fields[k];
2741 return option;
2744 /****************************************************************
2745 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2747 * before replying OK: status=0 a rpc call is made to the workstation
2748 * asking ReplyOpenPrinter
2750 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2751 * called from api_spoolss_rffpcnex
2752 ****************************************************************/
2754 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2755 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2757 int snum = -1;
2758 struct spoolss_NotifyOption *option = r->in.notify_options;
2759 struct sockaddr_storage client_ss;
2761 /* store the notify value in the printer struct */
2763 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2765 if (!Printer) {
2766 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2767 "Invalid handle (%s:%u:%u).\n",
2768 OUR_HANDLE(r->in.handle)));
2769 return WERR_BADFID;
2772 Printer->notify.flags = r->in.flags;
2773 Printer->notify.options = r->in.options;
2774 Printer->notify.printerlocal = r->in.printer_local;
2776 TALLOC_FREE(Printer->notify.option);
2777 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2779 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2781 /* Connect to the client machine and send a ReplyOpenPrinter */
2783 if ( Printer->printer_type == SPLHND_SERVER)
2784 snum = -1;
2785 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2786 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2787 return WERR_BADFID;
2789 if (!interpret_string_addr(&client_ss, p->client_address,
2790 AI_NUMERICHOST)) {
2791 return WERR_SERVER_UNAVAILABLE;
2794 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2795 Printer->notify.printerlocal, 1,
2796 &Printer->notify.client_hnd, &client_ss))
2797 return WERR_SERVER_UNAVAILABLE;
2799 Printer->notify.client_connected = true;
2801 return WERR_OK;
2804 /*******************************************************************
2805 * fill a notify_info_data with the servername
2806 ********************************************************************/
2808 void spoolss_notify_server_name(int snum,
2809 struct spoolss_Notify *data,
2810 print_queue_struct *queue,
2811 NT_PRINTER_INFO_LEVEL *printer,
2812 TALLOC_CTX *mem_ctx)
2814 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2817 /*******************************************************************
2818 * fill a notify_info_data with the printername (not including the servername).
2819 ********************************************************************/
2821 void spoolss_notify_printer_name(int snum,
2822 struct spoolss_Notify *data,
2823 print_queue_struct *queue,
2824 NT_PRINTER_INFO_LEVEL *printer,
2825 TALLOC_CTX *mem_ctx)
2827 /* the notify name should not contain the \\server\ part */
2828 char *p = strrchr(printer->info_2->printername, '\\');
2830 if (!p) {
2831 p = printer->info_2->printername;
2832 } else {
2833 p++;
2836 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2839 /*******************************************************************
2840 * fill a notify_info_data with the servicename
2841 ********************************************************************/
2843 void spoolss_notify_share_name(int snum,
2844 struct spoolss_Notify *data,
2845 print_queue_struct *queue,
2846 NT_PRINTER_INFO_LEVEL *printer,
2847 TALLOC_CTX *mem_ctx)
2849 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2852 /*******************************************************************
2853 * fill a notify_info_data with the port name
2854 ********************************************************************/
2856 void spoolss_notify_port_name(int snum,
2857 struct spoolss_Notify *data,
2858 print_queue_struct *queue,
2859 NT_PRINTER_INFO_LEVEL *printer,
2860 TALLOC_CTX *mem_ctx)
2862 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2865 /*******************************************************************
2866 * fill a notify_info_data with the printername
2867 * but it doesn't exist, have to see what to do
2868 ********************************************************************/
2870 void spoolss_notify_driver_name(int snum,
2871 struct spoolss_Notify *data,
2872 print_queue_struct *queue,
2873 NT_PRINTER_INFO_LEVEL *printer,
2874 TALLOC_CTX *mem_ctx)
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2879 /*******************************************************************
2880 * fill a notify_info_data with the comment
2881 ********************************************************************/
2883 void spoolss_notify_comment(int snum,
2884 struct spoolss_Notify *data,
2885 print_queue_struct *queue,
2886 NT_PRINTER_INFO_LEVEL *printer,
2887 TALLOC_CTX *mem_ctx)
2889 char *p;
2891 if (*printer->info_2->comment == '\0') {
2892 p = lp_comment(snum);
2893 } else {
2894 p = printer->info_2->comment;
2897 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2900 /*******************************************************************
2901 * fill a notify_info_data with the comment
2902 * location = "Room 1, floor 2, building 3"
2903 ********************************************************************/
2905 void spoolss_notify_location(int snum,
2906 struct spoolss_Notify *data,
2907 print_queue_struct *queue,
2908 NT_PRINTER_INFO_LEVEL *printer,
2909 TALLOC_CTX *mem_ctx)
2911 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2914 /*******************************************************************
2915 * fill a notify_info_data with the device mode
2916 * jfm:xxxx don't to it for know but that's a real problem !!!
2917 ********************************************************************/
2919 static void spoolss_notify_devmode(int snum,
2920 struct spoolss_Notify *data,
2921 print_queue_struct *queue,
2922 NT_PRINTER_INFO_LEVEL *printer,
2923 TALLOC_CTX *mem_ctx)
2925 /* for a dummy implementation we have to zero the fields */
2926 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2929 /*******************************************************************
2930 * fill a notify_info_data with the separator file name
2931 ********************************************************************/
2933 void spoolss_notify_sepfile(int snum,
2934 struct spoolss_Notify *data,
2935 print_queue_struct *queue,
2936 NT_PRINTER_INFO_LEVEL *printer,
2937 TALLOC_CTX *mem_ctx)
2939 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2942 /*******************************************************************
2943 * fill a notify_info_data with the print processor
2944 * jfm:xxxx return always winprint to indicate we don't do anything to it
2945 ********************************************************************/
2947 void spoolss_notify_print_processor(int snum,
2948 struct spoolss_Notify *data,
2949 print_queue_struct *queue,
2950 NT_PRINTER_INFO_LEVEL *printer,
2951 TALLOC_CTX *mem_ctx)
2953 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2956 /*******************************************************************
2957 * fill a notify_info_data with the print processor options
2958 * jfm:xxxx send an empty string
2959 ********************************************************************/
2961 void spoolss_notify_parameters(int snum,
2962 struct spoolss_Notify *data,
2963 print_queue_struct *queue,
2964 NT_PRINTER_INFO_LEVEL *printer,
2965 TALLOC_CTX *mem_ctx)
2967 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2970 /*******************************************************************
2971 * fill a notify_info_data with the data type
2972 * jfm:xxxx always send RAW as data type
2973 ********************************************************************/
2975 void spoolss_notify_datatype(int snum,
2976 struct spoolss_Notify *data,
2977 print_queue_struct *queue,
2978 NT_PRINTER_INFO_LEVEL *printer,
2979 TALLOC_CTX *mem_ctx)
2981 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2984 /*******************************************************************
2985 * fill a notify_info_data with the security descriptor
2986 * jfm:xxxx send an null pointer to say no security desc
2987 * have to implement security before !
2988 ********************************************************************/
2990 static void spoolss_notify_security_desc(int snum,
2991 struct spoolss_Notify *data,
2992 print_queue_struct *queue,
2993 NT_PRINTER_INFO_LEVEL *printer,
2994 TALLOC_CTX *mem_ctx)
2996 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2997 printer->info_2->secdesc_buf->sd_size,
2998 printer->info_2->secdesc_buf->sd);
3001 /*******************************************************************
3002 * fill a notify_info_data with the attributes
3003 * jfm:xxxx a samba printer is always shared
3004 ********************************************************************/
3006 void spoolss_notify_attributes(int snum,
3007 struct spoolss_Notify *data,
3008 print_queue_struct *queue,
3009 NT_PRINTER_INFO_LEVEL *printer,
3010 TALLOC_CTX *mem_ctx)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3015 /*******************************************************************
3016 * fill a notify_info_data with the priority
3017 ********************************************************************/
3019 static void spoolss_notify_priority(int snum,
3020 struct spoolss_Notify *data,
3021 print_queue_struct *queue,
3022 NT_PRINTER_INFO_LEVEL *printer,
3023 TALLOC_CTX *mem_ctx)
3025 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3028 /*******************************************************************
3029 * fill a notify_info_data with the default priority
3030 ********************************************************************/
3032 static void spoolss_notify_default_priority(int snum,
3033 struct spoolss_Notify *data,
3034 print_queue_struct *queue,
3035 NT_PRINTER_INFO_LEVEL *printer,
3036 TALLOC_CTX *mem_ctx)
3038 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3041 /*******************************************************************
3042 * fill a notify_info_data with the start time
3043 ********************************************************************/
3045 static void spoolss_notify_start_time(int snum,
3046 struct spoolss_Notify *data,
3047 print_queue_struct *queue,
3048 NT_PRINTER_INFO_LEVEL *printer,
3049 TALLOC_CTX *mem_ctx)
3051 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3054 /*******************************************************************
3055 * fill a notify_info_data with the until time
3056 ********************************************************************/
3058 static void spoolss_notify_until_time(int snum,
3059 struct spoolss_Notify *data,
3060 print_queue_struct *queue,
3061 NT_PRINTER_INFO_LEVEL *printer,
3062 TALLOC_CTX *mem_ctx)
3064 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3067 /*******************************************************************
3068 * fill a notify_info_data with the status
3069 ********************************************************************/
3071 static void spoolss_notify_status(int snum,
3072 struct spoolss_Notify *data,
3073 print_queue_struct *queue,
3074 NT_PRINTER_INFO_LEVEL *printer,
3075 TALLOC_CTX *mem_ctx)
3077 print_status_struct status;
3079 print_queue_length(snum, &status);
3080 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3083 /*******************************************************************
3084 * fill a notify_info_data with the number of jobs queued
3085 ********************************************************************/
3087 void spoolss_notify_cjobs(int snum,
3088 struct spoolss_Notify *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3093 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3096 /*******************************************************************
3097 * fill a notify_info_data with the average ppm
3098 ********************************************************************/
3100 static void spoolss_notify_average_ppm(int snum,
3101 struct spoolss_Notify *data,
3102 print_queue_struct *queue,
3103 NT_PRINTER_INFO_LEVEL *printer,
3104 TALLOC_CTX *mem_ctx)
3106 /* always respond 8 pages per minutes */
3107 /* a little hard ! */
3108 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3111 /*******************************************************************
3112 * fill a notify_info_data with username
3113 ********************************************************************/
3115 static void spoolss_notify_username(int snum,
3116 struct spoolss_Notify *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3124 /*******************************************************************
3125 * fill a notify_info_data with job status
3126 ********************************************************************/
3128 static void spoolss_notify_job_status(int snum,
3129 struct spoolss_Notify *data,
3130 print_queue_struct *queue,
3131 NT_PRINTER_INFO_LEVEL *printer,
3132 TALLOC_CTX *mem_ctx)
3134 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3137 /*******************************************************************
3138 * fill a notify_info_data with job name
3139 ********************************************************************/
3141 static void spoolss_notify_job_name(int snum,
3142 struct spoolss_Notify *data,
3143 print_queue_struct *queue,
3144 NT_PRINTER_INFO_LEVEL *printer,
3145 TALLOC_CTX *mem_ctx)
3147 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3150 /*******************************************************************
3151 * fill a notify_info_data with job status
3152 ********************************************************************/
3154 static void spoolss_notify_job_status_string(int snum,
3155 struct spoolss_Notify *data,
3156 print_queue_struct *queue,
3157 NT_PRINTER_INFO_LEVEL *printer,
3158 TALLOC_CTX *mem_ctx)
3161 * Now we're returning job status codes we just return a "" here. JRA.
3164 const char *p = "";
3166 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3167 p = "unknown";
3169 switch (queue->status) {
3170 case LPQ_QUEUED:
3171 p = "Queued";
3172 break;
3173 case LPQ_PAUSED:
3174 p = ""; /* NT provides the paused string */
3175 break;
3176 case LPQ_SPOOLING:
3177 p = "Spooling";
3178 break;
3179 case LPQ_PRINTING:
3180 p = "Printing";
3181 break;
3183 #endif /* NO LONGER NEEDED. */
3185 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3188 /*******************************************************************
3189 * fill a notify_info_data with job time
3190 ********************************************************************/
3192 static void spoolss_notify_job_time(int snum,
3193 struct spoolss_Notify *data,
3194 print_queue_struct *queue,
3195 NT_PRINTER_INFO_LEVEL *printer,
3196 TALLOC_CTX *mem_ctx)
3198 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3201 /*******************************************************************
3202 * fill a notify_info_data with job size
3203 ********************************************************************/
3205 static void spoolss_notify_job_size(int snum,
3206 struct spoolss_Notify *data,
3207 print_queue_struct *queue,
3208 NT_PRINTER_INFO_LEVEL *printer,
3209 TALLOC_CTX *mem_ctx)
3211 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3214 /*******************************************************************
3215 * fill a notify_info_data with page info
3216 ********************************************************************/
3217 static void spoolss_notify_total_pages(int snum,
3218 struct spoolss_Notify *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3223 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3226 /*******************************************************************
3227 * fill a notify_info_data with pages printed info.
3228 ********************************************************************/
3229 static void spoolss_notify_pages_printed(int snum,
3230 struct spoolss_Notify *data,
3231 print_queue_struct *queue,
3232 NT_PRINTER_INFO_LEVEL *printer,
3233 TALLOC_CTX *mem_ctx)
3235 /* Add code when back-end tracks this */
3236 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3239 /*******************************************************************
3240 Fill a notify_info_data with job position.
3241 ********************************************************************/
3243 static void spoolss_notify_job_position(int snum,
3244 struct spoolss_Notify *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3252 /*******************************************************************
3253 Fill a notify_info_data with submitted time.
3254 ********************************************************************/
3256 static void spoolss_notify_submitted_time(int snum,
3257 struct spoolss_Notify *data,
3258 print_queue_struct *queue,
3259 NT_PRINTER_INFO_LEVEL *printer,
3260 TALLOC_CTX *mem_ctx)
3262 data->data.string.string = NULL;
3263 data->data.string.size = 0;
3265 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3266 &data->data.string.string,
3267 &data->data.string.size);
3271 struct s_notify_info_data_table
3273 enum spoolss_NotifyType type;
3274 uint16_t field;
3275 const char *name;
3276 enum spoolss_NotifyTable variable_type;
3277 void (*fn) (int snum, struct spoolss_Notify *data,
3278 print_queue_struct *queue,
3279 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3282 /* A table describing the various print notification constants and
3283 whether the notification data is a pointer to a variable sized
3284 buffer, a one value uint32_t or a two value uint32_t. */
3286 static const struct s_notify_info_data_table notify_info_data_table[] =
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3339 /*******************************************************************
3340 Return the variable_type of info_data structure.
3341 ********************************************************************/
3343 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3344 uint16_t field)
3346 int i=0;
3348 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3349 if ( (notify_info_data_table[i].type == type) &&
3350 (notify_info_data_table[i].field == field) ) {
3351 return notify_info_data_table[i].variable_type;
3355 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3357 return 0;
3360 /****************************************************************************
3361 ****************************************************************************/
3363 static bool search_notify(enum spoolss_NotifyType type,
3364 uint16_t field,
3365 int *value)
3367 int i;
3369 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3370 if (notify_info_data_table[i].type == type &&
3371 notify_info_data_table[i].field == field &&
3372 notify_info_data_table[i].fn != NULL) {
3373 *value = i;
3374 return true;
3378 return false;
3381 /****************************************************************************
3382 ****************************************************************************/
3384 void construct_info_data(struct spoolss_Notify *info_data,
3385 enum spoolss_NotifyType type,
3386 uint16_t field,
3387 int id)
3389 info_data->type = type;
3390 info_data->field.field = field;
3391 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3392 info_data->job_id = id;
3395 /*******************************************************************
3397 * fill a notify_info struct with info asked
3399 ********************************************************************/
3401 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3402 struct spoolss_NotifyInfo *info,
3403 int snum,
3404 const struct spoolss_NotifyOptionType *option_type,
3405 uint32_t id,
3406 TALLOC_CTX *mem_ctx)
3408 int field_num,j;
3409 enum spoolss_NotifyType type;
3410 uint16_t field;
3412 struct spoolss_Notify *current_data;
3413 NT_PRINTER_INFO_LEVEL *printer = NULL;
3414 print_queue_struct *queue=NULL;
3416 type = option_type->type;
3418 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3419 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3420 option_type->count, lp_servicename(snum)));
3422 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3423 return false;
3425 for(field_num=0; field_num < option_type->count; field_num++) {
3426 field = option_type->fields[field_num].field;
3428 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3430 if (!search_notify(type, field, &j) )
3431 continue;
3433 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3434 struct spoolss_Notify,
3435 info->count + 1);
3436 if (info->notifies == NULL) {
3437 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3438 free_a_printer(&printer, 2);
3439 return false;
3442 current_data = &info->notifies[info->count];
3444 construct_info_data(current_data, type, field, id);
3446 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3447 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3449 notify_info_data_table[j].fn(snum, current_data, queue,
3450 printer, mem_ctx);
3452 info->count++;
3455 free_a_printer(&printer, 2);
3456 return true;
3459 /*******************************************************************
3461 * fill a notify_info struct with info asked
3463 ********************************************************************/
3465 static bool construct_notify_jobs_info(print_queue_struct *queue,
3466 struct spoolss_NotifyInfo *info,
3467 NT_PRINTER_INFO_LEVEL *printer,
3468 int snum,
3469 const struct spoolss_NotifyOptionType *option_type,
3470 uint32_t id,
3471 TALLOC_CTX *mem_ctx)
3473 int field_num,j;
3474 enum spoolss_NotifyType type;
3475 uint16_t field;
3476 struct spoolss_Notify *current_data;
3478 DEBUG(4,("construct_notify_jobs_info\n"));
3480 type = option_type->type;
3482 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3483 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3484 option_type->count));
3486 for(field_num=0; field_num<option_type->count; field_num++) {
3487 field = option_type->fields[field_num].field;
3489 if (!search_notify(type, field, &j) )
3490 continue;
3492 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3493 struct spoolss_Notify,
3494 info->count + 1);
3495 if (info->notifies == NULL) {
3496 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3497 return false;
3500 current_data=&(info->notifies[info->count]);
3502 construct_info_data(current_data, type, field, id);
3503 notify_info_data_table[j].fn(snum, current_data, queue,
3504 printer, mem_ctx);
3505 info->count++;
3508 return true;
3512 * JFM: The enumeration is not that simple, it's even non obvious.
3514 * let's take an example: I want to monitor the PRINTER SERVER for
3515 * the printer's name and the number of jobs currently queued.
3516 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3517 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3519 * I have 3 printers on the back of my server.
3521 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3522 * structures.
3523 * Number Data Id
3524 * 1 printer 1 name 1
3525 * 2 printer 1 cjob 1
3526 * 3 printer 2 name 2
3527 * 4 printer 2 cjob 2
3528 * 5 printer 3 name 3
3529 * 6 printer 3 name 3
3531 * that's the print server case, the printer case is even worse.
3534 /*******************************************************************
3536 * enumerate all printers on the printserver
3537 * fill a notify_info struct with info asked
3539 ********************************************************************/
3541 static WERROR printserver_notify_info(pipes_struct *p,
3542 struct policy_handle *hnd,
3543 struct spoolss_NotifyInfo *info,
3544 TALLOC_CTX *mem_ctx)
3546 int snum;
3547 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3548 int n_services=lp_numservices();
3549 int i;
3550 struct spoolss_NotifyOption *option;
3551 struct spoolss_NotifyOptionType option_type;
3553 DEBUG(4,("printserver_notify_info\n"));
3555 if (!Printer)
3556 return WERR_BADFID;
3558 option = Printer->notify.option;
3560 info->version = 2;
3561 info->notifies = NULL;
3562 info->count = 0;
3564 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3565 sending a ffpcn() request first */
3567 if ( !option )
3568 return WERR_BADFID;
3570 for (i=0; i<option->count; i++) {
3571 option_type = option->types[i];
3573 if (option_type.type != PRINTER_NOTIFY_TYPE)
3574 continue;
3576 for (snum=0; snum<n_services; snum++)
3578 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3579 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3583 #if 0
3585 * Debugging information, don't delete.
3588 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3589 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3590 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3592 for (i=0; i<info->count; i++) {
3593 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3594 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3595 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3597 #endif
3599 return WERR_OK;
3602 /*******************************************************************
3604 * fill a notify_info struct with info asked
3606 ********************************************************************/
3608 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3609 struct spoolss_NotifyInfo *info,
3610 TALLOC_CTX *mem_ctx)
3612 int snum;
3613 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3614 int i;
3615 uint32_t id;
3616 struct spoolss_NotifyOption *option;
3617 struct spoolss_NotifyOptionType option_type;
3618 int count,j;
3619 print_queue_struct *queue=NULL;
3620 print_status_struct status;
3622 DEBUG(4,("printer_notify_info\n"));
3624 if (!Printer)
3625 return WERR_BADFID;
3627 option = Printer->notify.option;
3628 id = 0x0;
3630 info->version = 2;
3631 info->notifies = NULL;
3632 info->count = 0;
3634 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3635 sending a ffpcn() request first */
3637 if ( !option )
3638 return WERR_BADFID;
3640 get_printer_snum(p, hnd, &snum, NULL);
3642 for (i=0; i<option->count; i++) {
3643 option_type = option->types[i];
3645 switch (option_type.type) {
3646 case PRINTER_NOTIFY_TYPE:
3647 if(construct_notify_printer_info(Printer, info, snum,
3648 &option_type, id,
3649 mem_ctx))
3650 id--;
3651 break;
3653 case JOB_NOTIFY_TYPE: {
3654 NT_PRINTER_INFO_LEVEL *printer = NULL;
3656 count = print_queue_status(snum, &queue, &status);
3658 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3659 goto done;
3661 for (j=0; j<count; j++) {
3662 construct_notify_jobs_info(&queue[j], info,
3663 printer, snum,
3664 &option_type,
3665 queue[j].job,
3666 mem_ctx);
3669 free_a_printer(&printer, 2);
3671 done:
3672 SAFE_FREE(queue);
3673 break;
3679 * Debugging information, don't delete.
3682 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3683 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3684 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3686 for (i=0; i<info->count; i++) {
3687 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3688 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3689 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3692 return WERR_OK;
3695 /****************************************************************
3696 _spoolss_RouterRefreshPrinterChangeNotify
3697 ****************************************************************/
3699 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3700 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3702 struct spoolss_NotifyInfo *info;
3704 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3705 WERROR result = WERR_BADFID;
3707 /* we always have a spoolss_NotifyInfo struct */
3708 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3709 if (!info) {
3710 result = WERR_NOMEM;
3711 goto done;
3714 *r->out.info = info;
3716 if (!Printer) {
3717 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3718 "Invalid handle (%s:%u:%u).\n",
3719 OUR_HANDLE(r->in.handle)));
3720 goto done;
3723 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3726 * We are now using the change value, and
3727 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3728 * I don't have a global notification system, I'm sending back all the
3729 * informations even when _NOTHING_ has changed.
3732 /* We need to keep track of the change value to send back in
3733 RRPCN replies otherwise our updates are ignored. */
3735 Printer->notify.fnpcn = true;
3737 if (Printer->notify.client_connected) {
3738 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3739 "Saving change value in request [%x]\n",
3740 r->in.change_low));
3741 Printer->notify.change = r->in.change_low;
3744 /* just ignore the spoolss_NotifyOption */
3746 switch (Printer->printer_type) {
3747 case SPLHND_SERVER:
3748 result = printserver_notify_info(p, r->in.handle,
3749 info, p->mem_ctx);
3750 break;
3752 case SPLHND_PRINTER:
3753 result = printer_notify_info(p, r->in.handle,
3754 info, p->mem_ctx);
3755 break;
3758 Printer->notify.fnpcn = false;
3760 done:
3761 return result;
3764 /********************************************************************
3765 * construct_printer_info_0
3766 * fill a printer_info_0 struct
3767 ********************************************************************/
3769 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3770 const NT_PRINTER_INFO_LEVEL *ntprinter,
3771 struct spoolss_PrinterInfo0 *r,
3772 int snum)
3774 int count;
3775 counter_printer_0 *session_counter;
3776 time_t setuptime;
3777 print_status_struct status;
3779 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3780 W_ERROR_HAVE_NO_MEMORY(r->printername);
3782 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3783 W_ERROR_HAVE_NO_MEMORY(r->servername);
3785 count = print_queue_length(snum, &status);
3787 /* check if we already have a counter for this printer */
3788 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3789 if (session_counter->snum == snum)
3790 break;
3793 /* it's the first time, add it to the list */
3794 if (session_counter == NULL) {
3795 session_counter = SMB_MALLOC_P(counter_printer_0);
3796 W_ERROR_HAVE_NO_MEMORY(session_counter);
3797 ZERO_STRUCTP(session_counter);
3798 session_counter->snum = snum;
3799 session_counter->counter = 0;
3800 DLIST_ADD(counter_list, session_counter);
3803 /* increment it */
3804 session_counter->counter++;
3806 r->cjobs = count;
3807 r->total_jobs = 0;
3808 r->total_bytes = 0;
3810 setuptime = (time_t)ntprinter->info_2->setuptime;
3812 init_systemtime(&r->time, gmtime(&setuptime));
3814 /* JFM:
3815 * the global_counter should be stored in a TDB as it's common to all the clients
3816 * and should be zeroed on samba startup
3818 r->global_counter = session_counter->counter;
3819 r->total_pages = 0;
3820 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3821 r->version = 0x0005; /* NT 5 */
3822 r->free_build = 0x0893; /* build 2195 */
3823 r->spooling = 0;
3824 r->max_spooling = 0;
3825 r->session_counter = session_counter->counter;
3826 r->num_error_out_of_paper = 0x0;
3827 r->num_error_not_ready = 0x0; /* number of print failure */
3828 r->job_error = 0x0;
3829 r->number_of_processors = 0x1;
3830 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3831 r->high_part_total_bytes = 0x0;
3832 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3833 r->last_error = WERR_OK;
3834 r->status = nt_printq_status(status.status);
3835 r->enumerate_network_printers = 0x0;
3836 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3837 r->processor_architecture = 0x0;
3838 r->processor_level = 0x6; /* 6 ???*/
3839 r->ref_ic = 0;
3840 r->reserved2 = 0;
3841 r->reserved3 = 0;
3843 return WERR_OK;
3846 /****************************************************************************
3847 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3848 should be valid upon entry
3849 ****************************************************************************/
3851 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3852 struct spoolss_DeviceMode *r,
3853 const NT_DEVICEMODE *ntdevmode)
3855 if (!r || !ntdevmode) {
3856 return WERR_INVALID_PARAM;
3859 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3860 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3862 r->specversion = ntdevmode->specversion;
3863 r->driverversion = ntdevmode->driverversion;
3864 r->size = ntdevmode->size;
3865 r->__driverextra_length = ntdevmode->driverextra;
3866 r->fields = ntdevmode->fields;
3868 r->orientation = ntdevmode->orientation;
3869 r->papersize = ntdevmode->papersize;
3870 r->paperlength = ntdevmode->paperlength;
3871 r->paperwidth = ntdevmode->paperwidth;
3872 r->scale = ntdevmode->scale;
3873 r->copies = ntdevmode->copies;
3874 r->defaultsource = ntdevmode->defaultsource;
3875 r->printquality = ntdevmode->printquality;
3876 r->color = ntdevmode->color;
3877 r->duplex = ntdevmode->duplex;
3878 r->yresolution = ntdevmode->yresolution;
3879 r->ttoption = ntdevmode->ttoption;
3880 r->collate = ntdevmode->collate;
3882 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3883 W_ERROR_HAVE_NO_MEMORY(r->formname);
3885 /* all 0 below are values that have not been set in the old parsing/copy
3886 * function, maybe they should... - gd */
3888 r->logpixels = 0;
3889 r->bitsperpel = 0;
3890 r->pelswidth = 0;
3891 r->pelsheight = 0;
3892 r->displayflags = 0;
3893 r->displayfrequency = 0;
3894 r->icmmethod = ntdevmode->icmmethod;
3895 r->icmintent = ntdevmode->icmintent;
3896 r->mediatype = ntdevmode->mediatype;
3897 r->dithertype = ntdevmode->dithertype;
3898 r->reserved1 = 0;
3899 r->reserved2 = 0;
3900 r->panningwidth = 0;
3901 r->panningheight = 0;
3903 if (ntdevmode->nt_dev_private != NULL) {
3904 r->driverextra_data = data_blob_talloc(mem_ctx,
3905 ntdevmode->nt_dev_private,
3906 ntdevmode->driverextra);
3907 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3910 return WERR_OK;
3914 /****************************************************************************
3915 Create a spoolss_DeviceMode struct. Returns talloced memory.
3916 ****************************************************************************/
3918 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3919 const char *servicename)
3921 WERROR result;
3922 NT_PRINTER_INFO_LEVEL *printer = NULL;
3923 struct spoolss_DeviceMode *devmode = NULL;
3925 DEBUG(7,("construct_dev_mode\n"));
3927 DEBUGADD(8,("getting printer characteristics\n"));
3929 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3930 return NULL;
3932 if (!printer->info_2->devmode) {
3933 DEBUG(5, ("BONG! There was no device mode!\n"));
3934 goto done;
3937 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3938 if (!devmode) {
3939 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3940 goto done;
3943 DEBUGADD(8,("loading DEVICEMODE\n"));
3945 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3946 if (!W_ERROR_IS_OK(result)) {
3947 TALLOC_FREE(devmode);
3950 done:
3951 free_a_printer(&printer,2);
3953 return devmode;
3956 /********************************************************************
3957 * construct_printer_info3
3958 * fill a spoolss_PrinterInfo3 struct
3959 ********************************************************************/
3961 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3962 const NT_PRINTER_INFO_LEVEL *ntprinter,
3963 struct spoolss_PrinterInfo3 *r,
3964 int snum)
3966 /* These are the components of the SD we are returning. */
3968 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3969 /* don't use talloc_steal() here unless you do a deep steal of all
3970 the SEC_DESC members */
3972 r->secdesc = dup_sec_desc(mem_ctx,
3973 ntprinter->info_2->secdesc_buf->sd);
3974 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3977 return WERR_OK;
3980 /********************************************************************
3981 * construct_printer_info4
3982 * fill a spoolss_PrinterInfo4 struct
3983 ********************************************************************/
3985 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3986 const NT_PRINTER_INFO_LEVEL *ntprinter,
3987 struct spoolss_PrinterInfo4 *r,
3988 int snum)
3990 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3991 W_ERROR_HAVE_NO_MEMORY(r->printername);
3992 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3993 W_ERROR_HAVE_NO_MEMORY(r->servername);
3995 r->attributes = ntprinter->info_2->attributes;
3997 return WERR_OK;
4000 /********************************************************************
4001 * construct_printer_info5
4002 * fill a spoolss_PrinterInfo5 struct
4003 ********************************************************************/
4005 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4006 const NT_PRINTER_INFO_LEVEL *ntprinter,
4007 struct spoolss_PrinterInfo5 *r,
4008 int snum)
4010 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4011 W_ERROR_HAVE_NO_MEMORY(r->printername);
4012 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4013 W_ERROR_HAVE_NO_MEMORY(r->portname);
4015 r->attributes = ntprinter->info_2->attributes;
4017 /* these two are not used by NT+ according to MSDN */
4019 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4020 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4022 return WERR_OK;
4025 /********************************************************************
4026 * construct_printer_info_6
4027 * fill a spoolss_PrinterInfo6 struct
4028 ********************************************************************/
4030 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4031 const NT_PRINTER_INFO_LEVEL *ntprinter,
4032 struct spoolss_PrinterInfo6 *r,
4033 int snum)
4035 int count;
4036 print_status_struct status;
4038 count = print_queue_length(snum, &status);
4040 r->status = nt_printq_status(status.status);
4042 return WERR_OK;
4045 /********************************************************************
4046 * construct_printer_info7
4047 * fill a spoolss_PrinterInfo7 struct
4048 ********************************************************************/
4050 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4051 Printer_entry *print_hnd,
4052 struct spoolss_PrinterInfo7 *r,
4053 int snum)
4055 struct GUID guid;
4057 if (is_printer_published(print_hnd, snum, &guid)) {
4058 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4059 r->action = DSPRINT_PUBLISH;
4060 } else {
4061 r->guid = talloc_strdup(mem_ctx, "");
4062 r->action = DSPRINT_UNPUBLISH;
4064 W_ERROR_HAVE_NO_MEMORY(r->guid);
4066 return WERR_OK;
4069 /********************************************************************
4070 * construct_printer_info8
4071 * fill a spoolss_PrinterInfo8 struct
4072 ********************************************************************/
4074 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4075 const NT_PRINTER_INFO_LEVEL *ntprinter,
4076 struct spoolss_DeviceModeInfo *r,
4077 int snum)
4079 struct spoolss_DeviceMode *devmode;
4080 WERROR result;
4082 if (!ntprinter->info_2->devmode) {
4083 r->devmode = NULL;
4084 return WERR_OK;
4087 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4088 W_ERROR_HAVE_NO_MEMORY(devmode);
4090 result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4091 if (!W_ERROR_IS_OK(result)) {
4092 TALLOC_FREE(devmode);
4093 return result;
4096 r->devmode = devmode;
4098 return WERR_OK;
4102 /********************************************************************
4103 * construct_printer_info1
4104 * fill a spoolss_PrinterInfo1 struct
4105 ********************************************************************/
4107 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4108 const NT_PRINTER_INFO_LEVEL *ntprinter,
4109 uint32_t flags,
4110 struct spoolss_PrinterInfo1 *r,
4111 int snum)
4113 r->flags = flags;
4115 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4116 ntprinter->info_2->printername,
4117 ntprinter->info_2->drivername,
4118 ntprinter->info_2->location);
4119 W_ERROR_HAVE_NO_MEMORY(r->description);
4121 if (*ntprinter->info_2->comment == '\0') {
4122 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4123 } else {
4124 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4126 W_ERROR_HAVE_NO_MEMORY(r->comment);
4128 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4129 W_ERROR_HAVE_NO_MEMORY(r->name);
4131 return WERR_OK;
4134 /********************************************************************
4135 * construct_printer_info2
4136 * fill a spoolss_PrinterInfo2 struct
4137 ********************************************************************/
4139 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4140 const NT_PRINTER_INFO_LEVEL *ntprinter,
4141 struct spoolss_PrinterInfo2 *r,
4142 int snum)
4144 int count;
4146 print_status_struct status;
4148 count = print_queue_length(snum, &status);
4150 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4151 W_ERROR_HAVE_NO_MEMORY(r->servername);
4152 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4153 W_ERROR_HAVE_NO_MEMORY(r->printername);
4154 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4155 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4156 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4157 W_ERROR_HAVE_NO_MEMORY(r->portname);
4158 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4159 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4161 if (*ntprinter->info_2->comment == '\0') {
4162 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4163 } else {
4164 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4166 W_ERROR_HAVE_NO_MEMORY(r->comment);
4168 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4169 W_ERROR_HAVE_NO_MEMORY(r->location);
4170 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4171 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4172 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4173 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4174 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4175 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4176 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4177 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4179 r->attributes = ntprinter->info_2->attributes;
4181 r->priority = ntprinter->info_2->priority;
4182 r->defaultpriority = ntprinter->info_2->default_priority;
4183 r->starttime = ntprinter->info_2->starttime;
4184 r->untiltime = ntprinter->info_2->untiltime;
4185 r->status = nt_printq_status(status.status);
4186 r->cjobs = count;
4187 r->averageppm = ntprinter->info_2->averageppm;
4189 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4190 if (!r->devmode) {
4191 DEBUG(8,("Returning NULL Devicemode!\n"));
4194 r->secdesc = NULL;
4196 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4197 /* don't use talloc_steal() here unless you do a deep steal of all
4198 the SEC_DESC members */
4200 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4203 return WERR_OK;
4206 /********************************************************************
4207 ********************************************************************/
4209 static bool snum_is_shared_printer(int snum)
4211 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4214 /********************************************************************
4215 Spoolss_enumprinters.
4216 ********************************************************************/
4218 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4219 uint32_t level,
4220 uint32_t flags,
4221 union spoolss_PrinterInfo **info_p,
4222 uint32_t *count_p)
4224 int snum;
4225 int n_services = lp_numservices();
4226 union spoolss_PrinterInfo *info = NULL;
4227 uint32_t count = 0;
4228 WERROR result = WERR_OK;
4230 *count_p = 0;
4231 *info_p = NULL;
4233 for (snum = 0; snum < n_services; snum++) {
4235 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4237 if (!snum_is_shared_printer(snum)) {
4238 continue;
4241 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4242 lp_servicename(snum), snum));
4244 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4245 union spoolss_PrinterInfo,
4246 count + 1);
4247 if (!info) {
4248 result = WERR_NOMEM;
4249 goto out;
4252 result = get_a_printer(NULL, &ntprinter, 2,
4253 lp_const_servicename(snum));
4254 if (!W_ERROR_IS_OK(result)) {
4255 goto out;
4258 switch (level) {
4259 case 0:
4260 result = construct_printer_info0(info, ntprinter,
4261 &info[count].info0, snum);
4262 break;
4263 case 1:
4264 result = construct_printer_info1(info, ntprinter, flags,
4265 &info[count].info1, snum);
4266 break;
4267 case 2:
4268 result = construct_printer_info2(info, ntprinter,
4269 &info[count].info2, snum);
4270 break;
4271 case 4:
4272 result = construct_printer_info4(info, ntprinter,
4273 &info[count].info4, snum);
4274 break;
4275 case 5:
4276 result = construct_printer_info5(info, ntprinter,
4277 &info[count].info5, snum);
4278 break;
4280 default:
4281 result = WERR_UNKNOWN_LEVEL;
4282 free_a_printer(&ntprinter, 2);
4283 goto out;
4286 free_a_printer(&ntprinter, 2);
4287 if (!W_ERROR_IS_OK(result)) {
4288 goto out;
4291 count++;
4294 *count_p = count;
4295 *info_p = info;
4297 out:
4298 if (!W_ERROR_IS_OK(result)) {
4299 TALLOC_FREE(info);
4300 return result;
4303 *info_p = info;
4305 return WERR_OK;
4308 /********************************************************************
4309 * handle enumeration of printers at level 0
4310 ********************************************************************/
4312 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4313 uint32_t flags,
4314 const char *servername,
4315 union spoolss_PrinterInfo **info,
4316 uint32_t *count)
4318 DEBUG(4,("enum_all_printers_info_0\n"));
4320 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4324 /********************************************************************
4325 ********************************************************************/
4327 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4328 uint32_t flags,
4329 union spoolss_PrinterInfo **info,
4330 uint32_t *count)
4332 DEBUG(4,("enum_all_printers_info_1\n"));
4334 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4337 /********************************************************************
4338 enum_all_printers_info_1_local.
4339 *********************************************************************/
4341 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4342 union spoolss_PrinterInfo **info,
4343 uint32_t *count)
4345 DEBUG(4,("enum_all_printers_info_1_local\n"));
4347 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4350 /********************************************************************
4351 enum_all_printers_info_1_name.
4352 *********************************************************************/
4354 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4355 const char *name,
4356 union spoolss_PrinterInfo **info,
4357 uint32_t *count)
4359 const char *s = name;
4361 DEBUG(4,("enum_all_printers_info_1_name\n"));
4363 if ((name[0] == '\\') && (name[1] == '\\')) {
4364 s = name + 2;
4367 if (!is_myname_or_ipaddr(s)) {
4368 return WERR_INVALID_NAME;
4371 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4374 /********************************************************************
4375 enum_all_printers_info_1_network.
4376 *********************************************************************/
4378 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4379 const char *name,
4380 union spoolss_PrinterInfo **info,
4381 uint32_t *count)
4383 const char *s = name;
4385 DEBUG(4,("enum_all_printers_info_1_network\n"));
4387 /* If we respond to a enum_printers level 1 on our name with flags
4388 set to PRINTER_ENUM_REMOTE with a list of printers then these
4389 printers incorrectly appear in the APW browse list.
4390 Specifically the printers for the server appear at the workgroup
4391 level where all the other servers in the domain are
4392 listed. Windows responds to this call with a
4393 WERR_CAN_NOT_COMPLETE so we should do the same. */
4395 if (name[0] == '\\' && name[1] == '\\') {
4396 s = name + 2;
4399 if (is_myname_or_ipaddr(s)) {
4400 return WERR_CAN_NOT_COMPLETE;
4403 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4406 /********************************************************************
4407 * api_spoolss_enumprinters
4409 * called from api_spoolss_enumprinters (see this to understand)
4410 ********************************************************************/
4412 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4413 union spoolss_PrinterInfo **info,
4414 uint32_t *count)
4416 DEBUG(4,("enum_all_printers_info_2\n"));
4418 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4421 /********************************************************************
4422 * handle enumeration of printers at level 1
4423 ********************************************************************/
4425 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4426 uint32_t flags,
4427 const char *name,
4428 union spoolss_PrinterInfo **info,
4429 uint32_t *count)
4431 /* Not all the flags are equals */
4433 if (flags & PRINTER_ENUM_LOCAL) {
4434 return enum_all_printers_info_1_local(mem_ctx, info, count);
4437 if (flags & PRINTER_ENUM_NAME) {
4438 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4441 if (flags & PRINTER_ENUM_NETWORK) {
4442 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4445 return WERR_OK; /* NT4sp5 does that */
4448 /********************************************************************
4449 * handle enumeration of printers at level 2
4450 ********************************************************************/
4452 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4453 uint32_t flags,
4454 const char *servername,
4455 union spoolss_PrinterInfo **info,
4456 uint32_t *count)
4458 if (flags & PRINTER_ENUM_LOCAL) {
4459 return enum_all_printers_info_2(mem_ctx, info, count);
4462 if (flags & PRINTER_ENUM_NAME) {
4463 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4464 return WERR_INVALID_NAME;
4467 return enum_all_printers_info_2(mem_ctx, info, count);
4470 if (flags & PRINTER_ENUM_REMOTE) {
4471 return WERR_UNKNOWN_LEVEL;
4474 return WERR_OK;
4477 /********************************************************************
4478 * handle enumeration of printers at level 4
4479 ********************************************************************/
4481 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4482 uint32_t flags,
4483 const char *servername,
4484 union spoolss_PrinterInfo **info,
4485 uint32_t *count)
4487 DEBUG(4,("enum_all_printers_info_4\n"));
4489 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4493 /********************************************************************
4494 * handle enumeration of printers at level 5
4495 ********************************************************************/
4497 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4498 uint32_t flags,
4499 const char *servername,
4500 union spoolss_PrinterInfo **info,
4501 uint32_t *count)
4503 DEBUG(4,("enum_all_printers_info_5\n"));
4505 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4508 /****************************************************************
4509 _spoolss_EnumPrinters
4510 ****************************************************************/
4512 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4513 struct spoolss_EnumPrinters *r)
4515 const char *name;
4516 WERROR result;
4518 /* that's an [in out] buffer */
4520 if (!r->in.buffer && (r->in.offered != 0)) {
4521 return WERR_INVALID_PARAM;
4524 DEBUG(4,("_spoolss_EnumPrinters\n"));
4526 *r->out.needed = 0;
4527 *r->out.count = 0;
4528 *r->out.info = NULL;
4531 * Level 1:
4532 * flags==PRINTER_ENUM_NAME
4533 * if name=="" then enumerates all printers
4534 * if name!="" then enumerate the printer
4535 * flags==PRINTER_ENUM_REMOTE
4536 * name is NULL, enumerate printers
4537 * Level 2: name!="" enumerates printers, name can't be NULL
4538 * Level 3: doesn't exist
4539 * Level 4: does a local registry lookup
4540 * Level 5: same as Level 2
4543 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4544 W_ERROR_HAVE_NO_MEMORY(name);
4546 switch (r->in.level) {
4547 case 0:
4548 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4549 r->out.info, r->out.count);
4550 break;
4551 case 1:
4552 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4553 r->out.info, r->out.count);
4554 break;
4555 case 2:
4556 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4557 r->out.info, r->out.count);
4558 break;
4559 case 4:
4560 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4561 r->out.info, r->out.count);
4562 break;
4563 case 5:
4564 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4565 r->out.info, r->out.count);
4566 break;
4567 default:
4568 return WERR_UNKNOWN_LEVEL;
4571 if (!W_ERROR_IS_OK(result)) {
4572 return result;
4575 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4576 spoolss_EnumPrinters, NULL,
4577 *r->out.info, r->in.level,
4578 *r->out.count);
4579 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4580 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4582 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4585 /****************************************************************
4586 _spoolss_GetPrinter
4587 ****************************************************************/
4589 WERROR _spoolss_GetPrinter(pipes_struct *p,
4590 struct spoolss_GetPrinter *r)
4592 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4593 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4594 WERROR result = WERR_OK;
4596 int snum;
4598 /* that's an [in out] buffer */
4600 if (!r->in.buffer && (r->in.offered != 0)) {
4601 return WERR_INVALID_PARAM;
4604 *r->out.needed = 0;
4606 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4607 return WERR_BADFID;
4610 result = get_a_printer(Printer, &ntprinter, 2,
4611 lp_const_servicename(snum));
4612 if (!W_ERROR_IS_OK(result)) {
4613 return result;
4616 switch (r->in.level) {
4617 case 0:
4618 result = construct_printer_info0(p->mem_ctx, ntprinter,
4619 &r->out.info->info0, snum);
4620 break;
4621 case 1:
4622 result = construct_printer_info1(p->mem_ctx, ntprinter,
4623 PRINTER_ENUM_ICON8,
4624 &r->out.info->info1, snum);
4625 break;
4626 case 2:
4627 result = construct_printer_info2(p->mem_ctx, ntprinter,
4628 &r->out.info->info2, snum);
4629 break;
4630 case 3:
4631 result = construct_printer_info3(p->mem_ctx, ntprinter,
4632 &r->out.info->info3, snum);
4633 break;
4634 case 4:
4635 result = construct_printer_info4(p->mem_ctx, ntprinter,
4636 &r->out.info->info4, snum);
4637 break;
4638 case 5:
4639 result = construct_printer_info5(p->mem_ctx, ntprinter,
4640 &r->out.info->info5, snum);
4641 break;
4642 case 6:
4643 result = construct_printer_info6(p->mem_ctx, ntprinter,
4644 &r->out.info->info6, snum);
4645 break;
4646 case 7:
4647 result = construct_printer_info7(p->mem_ctx, Printer,
4648 &r->out.info->info7, snum);
4649 break;
4650 case 8:
4651 result = construct_printer_info8(p->mem_ctx, ntprinter,
4652 &r->out.info->info8, snum);
4653 break;
4654 default:
4655 result = WERR_UNKNOWN_LEVEL;
4656 break;
4659 free_a_printer(&ntprinter, 2);
4661 if (!W_ERROR_IS_OK(result)) {
4662 TALLOC_FREE(r->out.info);
4663 return result;
4666 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4667 r->out.info, r->in.level);
4668 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4670 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4673 /********************************************************************
4674 ********************************************************************/
4676 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4677 fstring *fstring_array,
4678 const char *cservername)
4680 int i, num_strings = 0;
4681 const char **array = NULL;
4683 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4685 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4686 cservername, fstring_array[i]);
4687 if (!str) {
4688 TALLOC_FREE(array);
4689 return NULL;
4693 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4694 TALLOC_FREE(array);
4695 return NULL;
4699 if (i > 0) {
4700 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4701 &array, &num_strings);
4704 return array;
4707 /********************************************************************
4708 * fill a spoolss_DriverInfo1 struct
4709 ********************************************************************/
4711 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4712 struct spoolss_DriverInfo1 *r,
4713 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4714 const char *servername,
4715 const char *architecture)
4717 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4718 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4720 return WERR_OK;
4723 /********************************************************************
4724 * fill a spoolss_DriverInfo2 struct
4725 ********************************************************************/
4727 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4728 struct spoolss_DriverInfo2 *r,
4729 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4730 const char *servername)
4733 const char *cservername = canon_servername(servername);
4735 r->version = driver->info_3->cversion;
4737 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4738 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4739 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4740 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4742 if (strlen(driver->info_3->driverpath)) {
4743 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4744 cservername, driver->info_3->driverpath);
4745 } else {
4746 r->driver_path = talloc_strdup(mem_ctx, "");
4748 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4750 if (strlen(driver->info_3->datafile)) {
4751 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4752 cservername, driver->info_3->datafile);
4753 } else {
4754 r->data_file = talloc_strdup(mem_ctx, "");
4756 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4758 if (strlen(driver->info_3->configfile)) {
4759 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4760 cservername, driver->info_3->configfile);
4761 } else {
4762 r->config_file = talloc_strdup(mem_ctx, "");
4764 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4766 return WERR_OK;
4769 /********************************************************************
4770 * fill a spoolss_DriverInfo3 struct
4771 ********************************************************************/
4773 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4774 struct spoolss_DriverInfo3 *r,
4775 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4776 const char *servername)
4778 const char *cservername = canon_servername(servername);
4780 r->version = driver->info_3->cversion;
4782 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4783 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4784 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4785 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4787 if (strlen(driver->info_3->driverpath)) {
4788 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4789 cservername, driver->info_3->driverpath);
4790 } else {
4791 r->driver_path = talloc_strdup(mem_ctx, "");
4793 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4795 if (strlen(driver->info_3->datafile)) {
4796 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4797 cservername, driver->info_3->datafile);
4798 } else {
4799 r->data_file = talloc_strdup(mem_ctx, "");
4801 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4803 if (strlen(driver->info_3->configfile)) {
4804 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4805 cservername, driver->info_3->configfile);
4806 } else {
4807 r->config_file = talloc_strdup(mem_ctx, "");
4809 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4811 if (strlen(driver->info_3->helpfile)) {
4812 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4813 cservername, driver->info_3->helpfile);
4814 } else {
4815 r->help_file = talloc_strdup(mem_ctx, "");
4817 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4819 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4820 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4821 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4822 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4824 r->dependent_files = string_array_from_driver_info(mem_ctx,
4825 driver->info_3->dependentfiles,
4826 cservername);
4827 return WERR_OK;
4830 /********************************************************************
4831 * fill a spoolss_DriverInfo4 struct
4832 ********************************************************************/
4834 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4835 struct spoolss_DriverInfo4 *r,
4836 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4837 const char *servername)
4839 const char *cservername = canon_servername(servername);
4841 r->version = driver->info_3->cversion;
4843 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4844 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4845 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4846 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4848 if (strlen(driver->info_3->driverpath)) {
4849 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4850 cservername, driver->info_3->driverpath);
4851 } else {
4852 r->driver_path = talloc_strdup(mem_ctx, "");
4854 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4856 if (strlen(driver->info_3->datafile)) {
4857 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4858 cservername, driver->info_3->datafile);
4859 } else {
4860 r->data_file = talloc_strdup(mem_ctx, "");
4862 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4864 if (strlen(driver->info_3->configfile)) {
4865 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4866 cservername, driver->info_3->configfile);
4867 } else {
4868 r->config_file = talloc_strdup(mem_ctx, "");
4870 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4872 if (strlen(driver->info_3->helpfile)) {
4873 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4874 cservername, driver->info_3->helpfile);
4875 } else {
4876 r->help_file = talloc_strdup(mem_ctx, "");
4878 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4880 r->dependent_files = string_array_from_driver_info(mem_ctx,
4881 driver->info_3->dependentfiles,
4882 cservername);
4885 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4886 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4887 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4888 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4890 r->previous_names = string_array_from_driver_info(mem_ctx,
4891 NULL,
4892 cservername);
4894 return WERR_OK;
4897 /********************************************************************
4898 * fill a spoolss_DriverInfo5 struct
4899 ********************************************************************/
4901 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4902 struct spoolss_DriverInfo5 *r,
4903 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4904 const char *servername)
4906 const char *cservername = canon_servername(servername);
4908 r->version = driver->info_3->cversion;
4910 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4911 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4912 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4913 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4915 if (strlen(driver->info_3->driverpath)) {
4916 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4917 cservername, driver->info_3->driverpath);
4918 } else {
4919 r->driver_path = talloc_strdup(mem_ctx, "");
4921 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4923 if (strlen(driver->info_3->datafile)) {
4924 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4925 cservername, driver->info_3->datafile);
4926 } else {
4927 r->data_file = talloc_strdup(mem_ctx, "");
4929 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4931 if (strlen(driver->info_3->configfile)) {
4932 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4933 cservername, driver->info_3->configfile);
4934 } else {
4935 r->config_file = talloc_strdup(mem_ctx, "");
4937 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4939 r->driver_attributes = 0;
4940 r->config_version = 0;
4941 r->driver_version = 0;
4943 return WERR_OK;
4945 /********************************************************************
4946 * fill a spoolss_DriverInfo6 struct
4947 ********************************************************************/
4949 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4950 struct spoolss_DriverInfo6 *r,
4951 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4952 const char *servername)
4954 const char *cservername = canon_servername(servername);
4956 r->version = driver->info_3->cversion;
4958 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4959 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4960 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4961 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4963 if (strlen(driver->info_3->driverpath)) {
4964 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4965 cservername, driver->info_3->driverpath);
4966 } else {
4967 r->driver_path = talloc_strdup(mem_ctx, "");
4969 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4971 if (strlen(driver->info_3->datafile)) {
4972 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4973 cservername, driver->info_3->datafile);
4974 } else {
4975 r->data_file = talloc_strdup(mem_ctx, "");
4977 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4979 if (strlen(driver->info_3->configfile)) {
4980 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4981 cservername, driver->info_3->configfile);
4982 } else {
4983 r->config_file = talloc_strdup(mem_ctx, "");
4985 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4987 if (strlen(driver->info_3->helpfile)) {
4988 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4989 cservername, driver->info_3->helpfile);
4990 } else {
4991 r->help_file = talloc_strdup(mem_ctx, "");
4993 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4995 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4996 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4997 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4998 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5000 r->dependent_files = string_array_from_driver_info(mem_ctx,
5001 driver->info_3->dependentfiles,
5002 cservername);
5003 r->previous_names = string_array_from_driver_info(mem_ctx,
5004 NULL,
5005 cservername);
5007 r->driver_date = 0;
5008 r->driver_version = 0;
5010 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5011 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5012 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5013 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5014 r->hardware_id = talloc_strdup(mem_ctx, "");
5015 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5016 r->provider = talloc_strdup(mem_ctx, "");
5017 W_ERROR_HAVE_NO_MEMORY(r->provider);
5019 return WERR_OK;
5022 /********************************************************************
5023 ********************************************************************/
5025 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5026 struct spoolss_DriverFileInfo *r,
5027 const char *cservername,
5028 const char *file_name,
5029 enum spoolss_DriverFileType file_type,
5030 uint32_t file_version)
5032 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5033 cservername, file_name);
5034 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5035 r->file_type = file_type;
5036 r->file_version = file_version;
5038 return WERR_OK;
5041 /********************************************************************
5042 ********************************************************************/
5044 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5045 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5046 const char *cservername,
5047 struct spoolss_DriverFileInfo **info_p,
5048 uint32_t *count_p)
5050 struct spoolss_DriverFileInfo *info = NULL;
5051 uint32_t count = 0;
5052 WERROR result;
5053 uint32_t i;
5055 *info_p = NULL;
5056 *count_p = 0;
5058 if (strlen(driver->info_3->driverpath)) {
5059 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5060 struct spoolss_DriverFileInfo,
5061 count + 1);
5062 W_ERROR_HAVE_NO_MEMORY(info);
5063 result = fill_spoolss_DriverFileInfo(info,
5064 &info[count],
5065 cservername,
5066 driver->info_3->driverpath,
5067 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5069 W_ERROR_NOT_OK_RETURN(result);
5070 count++;
5073 if (strlen(driver->info_3->configfile)) {
5074 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5075 struct spoolss_DriverFileInfo,
5076 count + 1);
5077 W_ERROR_HAVE_NO_MEMORY(info);
5078 result = fill_spoolss_DriverFileInfo(info,
5079 &info[count],
5080 cservername,
5081 driver->info_3->configfile,
5082 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5084 W_ERROR_NOT_OK_RETURN(result);
5085 count++;
5088 if (strlen(driver->info_3->datafile)) {
5089 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5090 struct spoolss_DriverFileInfo,
5091 count + 1);
5092 W_ERROR_HAVE_NO_MEMORY(info);
5093 result = fill_spoolss_DriverFileInfo(info,
5094 &info[count],
5095 cservername,
5096 driver->info_3->datafile,
5097 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5099 W_ERROR_NOT_OK_RETURN(result);
5100 count++;
5103 if (strlen(driver->info_3->helpfile)) {
5104 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5105 struct spoolss_DriverFileInfo,
5106 count + 1);
5107 W_ERROR_HAVE_NO_MEMORY(info);
5108 result = fill_spoolss_DriverFileInfo(info,
5109 &info[count],
5110 cservername,
5111 driver->info_3->helpfile,
5112 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5114 W_ERROR_NOT_OK_RETURN(result);
5115 count++;
5118 for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5119 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5120 struct spoolss_DriverFileInfo,
5121 count + 1);
5122 W_ERROR_HAVE_NO_MEMORY(info);
5123 result = fill_spoolss_DriverFileInfo(info,
5124 &info[count],
5125 cservername,
5126 driver->info_3->dependentfiles[i],
5127 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5129 W_ERROR_NOT_OK_RETURN(result);
5130 count++;
5133 *info_p = info;
5134 *count_p = count;
5136 return WERR_OK;
5139 /********************************************************************
5140 * fill a spoolss_DriverInfo101 sttruct
5141 ********************************************************************/
5143 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5144 struct spoolss_DriverInfo101 *r,
5145 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5146 const char *servername)
5148 const char *cservername = canon_servername(servername);
5149 WERROR result;
5151 r->version = driver->info_3->cversion;
5153 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
5154 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5155 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
5156 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5158 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5159 cservername,
5160 &r->file_info,
5161 &r->file_count);
5162 if (!W_ERROR_IS_OK(result)) {
5163 return result;
5166 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5167 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5169 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5170 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5172 r->previous_names = string_array_from_driver_info(mem_ctx,
5173 NULL,
5174 cservername);
5175 r->driver_date = 0;
5176 r->driver_version = 0;
5178 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5179 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5180 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5181 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5182 r->hardware_id = talloc_strdup(mem_ctx, "");
5183 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5184 r->provider = talloc_strdup(mem_ctx, "");
5185 W_ERROR_HAVE_NO_MEMORY(r->provider);
5187 return WERR_OK;
5190 /********************************************************************
5191 * construct_printer_driver_info_1
5192 ********************************************************************/
5194 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5195 struct spoolss_DriverInfo1 *r,
5196 int snum,
5197 const char *servername,
5198 const char *architecture,
5199 uint32_t version)
5201 NT_PRINTER_INFO_LEVEL *printer = NULL;
5202 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5203 WERROR result;
5205 ZERO_STRUCT(driver);
5207 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5208 return WERR_INVALID_PRINTER_NAME;
5210 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5211 free_a_printer(&printer, 2);
5212 return WERR_UNKNOWN_PRINTER_DRIVER;
5215 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5217 free_a_printer(&printer,2);
5219 return result;
5222 /********************************************************************
5223 * construct_printer_driver_info_2
5224 * fill a printer_info_2 struct
5225 ********************************************************************/
5227 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5228 struct spoolss_DriverInfo2 *r,
5229 int snum,
5230 const char *servername,
5231 const char *architecture,
5232 uint32_t version)
5234 NT_PRINTER_INFO_LEVEL *printer = NULL;
5235 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5236 WERROR result;
5238 ZERO_STRUCT(printer);
5239 ZERO_STRUCT(driver);
5241 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5242 return WERR_INVALID_PRINTER_NAME;
5244 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5245 free_a_printer(&printer, 2);
5246 return WERR_UNKNOWN_PRINTER_DRIVER;
5249 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5251 free_a_printer(&printer,2);
5253 return result;
5256 /********************************************************************
5257 * construct_printer_info_3
5258 * fill a printer_info_3 struct
5259 ********************************************************************/
5261 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5262 struct spoolss_DriverInfo3 *r,
5263 int snum,
5264 const char *servername,
5265 const char *architecture,
5266 uint32_t version)
5268 NT_PRINTER_INFO_LEVEL *printer = NULL;
5269 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5270 WERROR status;
5271 ZERO_STRUCT(driver);
5273 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5274 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5275 if (!W_ERROR_IS_OK(status))
5276 return WERR_INVALID_PRINTER_NAME;
5278 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5279 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5281 #if 0 /* JERRY */
5284 * I put this code in during testing. Helpful when commenting out the
5285 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5286 * as win2k always queries the driver using an infor level of 6.
5287 * I've left it in (but ifdef'd out) because I'll probably
5288 * use it in experimentation again in the future. --jerry 22/01/2002
5291 if (!W_ERROR_IS_OK(status)) {
5293 * Is this a W2k client ?
5295 if (version == 3) {
5296 /* Yes - try again with a WinNT driver. */
5297 version = 2;
5298 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5299 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5301 #endif
5303 if (!W_ERROR_IS_OK(status)) {
5304 free_a_printer(&printer,2);
5305 return WERR_UNKNOWN_PRINTER_DRIVER;
5308 #if 0 /* JERRY */
5310 #endif
5313 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5315 free_a_printer(&printer,2);
5317 return status;
5320 /********************************************************************
5321 * construct_printer_info_6
5322 * fill a printer_info_6 struct
5323 ********************************************************************/
5325 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5326 struct spoolss_DriverInfo6 *r,
5327 int snum,
5328 const char *servername,
5329 const char *architecture,
5330 uint32_t version)
5332 NT_PRINTER_INFO_LEVEL *printer = NULL;
5333 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5334 WERROR status;
5336 ZERO_STRUCT(driver);
5338 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5340 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5342 if (!W_ERROR_IS_OK(status))
5343 return WERR_INVALID_PRINTER_NAME;
5345 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5347 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5349 if (!W_ERROR_IS_OK(status))
5352 * Is this a W2k client ?
5355 if (version < 3) {
5356 free_a_printer(&printer,2);
5357 return WERR_UNKNOWN_PRINTER_DRIVER;
5360 /* Yes - try again with a WinNT driver. */
5361 version = 2;
5362 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5363 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5364 if (!W_ERROR_IS_OK(status)) {
5365 free_a_printer(&printer,2);
5366 return WERR_UNKNOWN_PRINTER_DRIVER;
5370 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5372 free_a_printer(&printer,2);
5373 free_a_printer_driver(driver, 3);
5375 return status;
5378 /********************************************************************
5379 * construct_printer_info_101
5380 * fill a printer_info_101 struct
5381 ********************************************************************/
5383 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5384 struct spoolss_DriverInfo101 *r,
5385 int snum,
5386 const char *servername,
5387 const char *architecture,
5388 uint32_t version)
5390 NT_PRINTER_INFO_LEVEL *printer = NULL;
5391 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5392 WERROR result;
5394 ZERO_STRUCT(driver);
5396 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5398 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5399 win_errstr(result)));
5401 if (!W_ERROR_IS_OK(result)) {
5402 return WERR_INVALID_PRINTER_NAME;
5405 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5406 architecture, version);
5408 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5409 win_errstr(result)));
5411 if (!W_ERROR_IS_OK(result)) {
5413 * Is this a W2k client ?
5416 if (version < 3) {
5417 free_a_printer(&printer, 2);
5418 return WERR_UNKNOWN_PRINTER_DRIVER;
5421 /* Yes - try again with a WinNT driver. */
5422 version = 2;
5423 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5424 architecture, version);
5425 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5426 win_errstr(result)));
5427 if (!W_ERROR_IS_OK(result)) {
5428 free_a_printer(&printer, 2);
5429 return WERR_UNKNOWN_PRINTER_DRIVER;
5433 result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5435 free_a_printer(&printer, 2);
5436 free_a_printer_driver(driver, 3);
5438 return result;
5441 /****************************************************************
5442 _spoolss_GetPrinterDriver2
5443 ****************************************************************/
5445 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5446 struct spoolss_GetPrinterDriver2 *r)
5448 Printer_entry *printer;
5449 WERROR result;
5451 const char *servername;
5452 int snum;
5454 /* that's an [in out] buffer */
5456 if (!r->in.buffer && (r->in.offered != 0)) {
5457 return WERR_INVALID_PARAM;
5460 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5462 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5463 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5464 return WERR_INVALID_PRINTER_NAME;
5467 *r->out.needed = 0;
5468 *r->out.server_major_version = 0;
5469 *r->out.server_minor_version = 0;
5471 servername = get_server_name(printer);
5473 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5474 return WERR_BADFID;
5477 switch (r->in.level) {
5478 case 1:
5479 result = construct_printer_driver_info_1(p->mem_ctx,
5480 &r->out.info->info1,
5481 snum,
5482 servername,
5483 r->in.architecture,
5484 r->in.client_major_version);
5485 break;
5486 case 2:
5487 result = construct_printer_driver_info_2(p->mem_ctx,
5488 &r->out.info->info2,
5489 snum,
5490 servername,
5491 r->in.architecture,
5492 r->in.client_major_version);
5493 break;
5494 case 3:
5495 result = construct_printer_driver_info_3(p->mem_ctx,
5496 &r->out.info->info3,
5497 snum,
5498 servername,
5499 r->in.architecture,
5500 r->in.client_major_version);
5501 break;
5502 case 6:
5503 result = construct_printer_driver_info_6(p->mem_ctx,
5504 &r->out.info->info6,
5505 snum,
5506 servername,
5507 r->in.architecture,
5508 r->in.client_major_version);
5509 break;
5510 case 101:
5511 result = construct_printer_driver_info_101(p->mem_ctx,
5512 &r->out.info->info101,
5513 snum,
5514 servername,
5515 r->in.architecture,
5516 r->in.client_major_version);
5517 break;
5518 default:
5519 result = WERR_UNKNOWN_LEVEL;
5520 break;
5523 if (!W_ERROR_IS_OK(result)) {
5524 TALLOC_FREE(r->out.info);
5525 return result;
5528 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5529 r->out.info, r->in.level);
5530 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5532 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5536 /****************************************************************
5537 _spoolss_StartPagePrinter
5538 ****************************************************************/
5540 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5541 struct spoolss_StartPagePrinter *r)
5543 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5545 if (!Printer) {
5546 DEBUG(3,("_spoolss_StartPagePrinter: "
5547 "Error in startpageprinter printer handle\n"));
5548 return WERR_BADFID;
5551 Printer->page_started = true;
5552 return WERR_OK;
5555 /****************************************************************
5556 _spoolss_EndPagePrinter
5557 ****************************************************************/
5559 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5560 struct spoolss_EndPagePrinter *r)
5562 int snum;
5564 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5566 if (!Printer) {
5567 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5568 OUR_HANDLE(r->in.handle)));
5569 return WERR_BADFID;
5572 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5573 return WERR_BADFID;
5575 Printer->page_started = false;
5576 print_job_endpage(snum, Printer->jobid);
5578 return WERR_OK;
5581 /****************************************************************
5582 _spoolss_StartDocPrinter
5583 ****************************************************************/
5585 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5586 struct spoolss_StartDocPrinter *r)
5588 struct spoolss_DocumentInfo1 *info_1;
5589 int snum;
5590 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5592 if (!Printer) {
5593 DEBUG(2,("_spoolss_StartDocPrinter: "
5594 "Invalid handle (%s:%u:%u)\n",
5595 OUR_HANDLE(r->in.handle)));
5596 return WERR_BADFID;
5599 if (r->in.level != 1) {
5600 return WERR_UNKNOWN_LEVEL;
5603 info_1 = r->in.info.info1;
5606 * a nice thing with NT is it doesn't listen to what you tell it.
5607 * when asked to send _only_ RAW datas, it tries to send datas
5608 * in EMF format.
5610 * So I add checks like in NT Server ...
5613 if (info_1->datatype) {
5614 if (strcmp(info_1->datatype, "RAW") != 0) {
5615 *r->out.job_id = 0;
5616 return WERR_INVALID_DATATYPE;
5620 /* get the share number of the printer */
5621 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5622 return WERR_BADFID;
5625 Printer->jobid = print_job_start(p->server_info, snum,
5626 info_1->document_name,
5627 Printer->nt_devmode);
5629 /* An error occured in print_job_start() so return an appropriate
5630 NT error code. */
5632 if (Printer->jobid == -1) {
5633 return map_werror_from_unix(errno);
5636 Printer->document_started = true;
5637 *r->out.job_id = Printer->jobid;
5639 return WERR_OK;
5642 /****************************************************************
5643 _spoolss_EndDocPrinter
5644 ****************************************************************/
5646 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5647 struct spoolss_EndDocPrinter *r)
5649 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5650 int snum;
5652 if (!Printer) {
5653 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5654 OUR_HANDLE(r->in.handle)));
5655 return WERR_BADFID;
5658 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5659 return WERR_BADFID;
5662 Printer->document_started = false;
5663 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5664 /* error codes unhandled so far ... */
5666 return WERR_OK;
5669 /****************************************************************
5670 _spoolss_WritePrinter
5671 ****************************************************************/
5673 WERROR _spoolss_WritePrinter(pipes_struct *p,
5674 struct spoolss_WritePrinter *r)
5676 uint32_t buffer_written;
5677 int snum;
5678 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5680 if (!Printer) {
5681 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5682 OUR_HANDLE(r->in.handle)));
5683 *r->out.num_written = r->in._data_size;
5684 return WERR_BADFID;
5687 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5688 return WERR_BADFID;
5690 buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5691 (const char *)r->in.data.data,
5692 (SMB_OFF_T)-1,
5693 (size_t)r->in._data_size);
5694 if (buffer_written == (uint32_t)-1) {
5695 *r->out.num_written = 0;
5696 if (errno == ENOSPC)
5697 return WERR_NO_SPOOL_SPACE;
5698 else
5699 return WERR_ACCESS_DENIED;
5702 *r->out.num_written = r->in._data_size;
5704 return WERR_OK;
5707 /********************************************************************
5708 * api_spoolss_getprinter
5709 * called from the spoolss dispatcher
5711 ********************************************************************/
5713 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5714 pipes_struct *p)
5716 int snum;
5717 WERROR errcode = WERR_BADFUNC;
5718 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5720 if (!Printer) {
5721 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5722 OUR_HANDLE(handle)));
5723 return WERR_BADFID;
5726 if (!get_printer_snum(p, handle, &snum, NULL))
5727 return WERR_BADFID;
5729 switch (command) {
5730 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5731 errcode = print_queue_pause(p->server_info, snum);
5732 break;
5733 case SPOOLSS_PRINTER_CONTROL_RESUME:
5734 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5735 errcode = print_queue_resume(p->server_info, snum);
5736 break;
5737 case SPOOLSS_PRINTER_CONTROL_PURGE:
5738 errcode = print_queue_purge(p->server_info, snum);
5739 break;
5740 default:
5741 return WERR_UNKNOWN_LEVEL;
5744 return errcode;
5748 /****************************************************************
5749 _spoolss_AbortPrinter
5750 * From MSDN: "Deletes printer's spool file if printer is configured
5751 * for spooling"
5752 ****************************************************************/
5754 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5755 struct spoolss_AbortPrinter *r)
5757 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5758 int snum;
5759 WERROR errcode = WERR_OK;
5761 if (!Printer) {
5762 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5763 OUR_HANDLE(r->in.handle)));
5764 return WERR_BADFID;
5767 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5768 return WERR_BADFID;
5770 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5772 return errcode;
5775 /********************************************************************
5776 * called by spoolss_api_setprinter
5777 * when updating a printer description
5778 ********************************************************************/
5780 static WERROR update_printer_sec(struct policy_handle *handle,
5781 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5783 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5784 WERROR result;
5785 int snum;
5787 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5789 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5790 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5791 OUR_HANDLE(handle)));
5793 result = WERR_BADFID;
5794 goto done;
5797 if (!secdesc_ctr) {
5798 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5799 result = WERR_INVALID_PARAM;
5800 goto done;
5803 /* Check the user has permissions to change the security
5804 descriptor. By experimentation with two NT machines, the user
5805 requires Full Access to the printer to change security
5806 information. */
5808 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5809 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5810 result = WERR_ACCESS_DENIED;
5811 goto done;
5814 /* NT seems to like setting the security descriptor even though
5815 nothing may have actually changed. */
5817 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5818 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5819 result = WERR_BADFID;
5820 goto done;
5823 if (DEBUGLEVEL >= 10) {
5824 SEC_ACL *the_acl;
5825 int i;
5827 the_acl = old_secdesc_ctr->sd->dacl;
5828 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5829 PRINTERNAME(snum), the_acl->num_aces));
5831 for (i = 0; i < the_acl->num_aces; i++) {
5832 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5833 &the_acl->aces[i].trustee),
5834 the_acl->aces[i].access_mask));
5837 the_acl = secdesc_ctr->sd->dacl;
5839 if (the_acl) {
5840 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5841 PRINTERNAME(snum), the_acl->num_aces));
5843 for (i = 0; i < the_acl->num_aces; i++) {
5844 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5845 &the_acl->aces[i].trustee),
5846 the_acl->aces[i].access_mask));
5848 } else {
5849 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5853 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5854 if (!new_secdesc_ctr) {
5855 result = WERR_NOMEM;
5856 goto done;
5859 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5860 result = WERR_OK;
5861 goto done;
5864 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5866 done:
5868 return result;
5871 /********************************************************************
5872 Canonicalize printer info from a client
5874 ATTN: It does not matter what we set the servername to hear
5875 since we do the necessary work in get_a_printer() to set it to
5876 the correct value based on what the client sent in the
5877 _spoolss_open_printer_ex().
5878 ********************************************************************/
5880 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5882 fstring printername;
5883 const char *p;
5885 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5886 "portname=%s drivername=%s comment=%s location=%s\n",
5887 info->servername, info->printername, info->sharename,
5888 info->portname, info->drivername, info->comment, info->location));
5890 /* we force some elements to "correct" values */
5891 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5892 fstrcpy(info->sharename, lp_servicename(snum));
5894 /* check to see if we allow printername != sharename */
5896 if ( lp_force_printername(snum) ) {
5897 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5898 global_myname(), info->sharename );
5899 } else {
5901 /* make sure printername is in \\server\printername format */
5903 fstrcpy( printername, info->printername );
5904 p = printername;
5905 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5906 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5907 p++;
5910 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5911 global_myname(), p );
5914 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5915 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5919 return true;
5922 /****************************************************************************
5923 ****************************************************************************/
5925 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5927 char *cmd = lp_addport_cmd();
5928 char *command = NULL;
5929 int ret;
5930 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5931 bool is_print_op = false;
5933 if ( !*cmd ) {
5934 return WERR_ACCESS_DENIED;
5937 command = talloc_asprintf(ctx,
5938 "%s \"%s\" \"%s\"", cmd, portname, uri );
5939 if (!command) {
5940 return WERR_NOMEM;
5943 if ( token )
5944 is_print_op = user_has_privileges( token, &se_printop );
5946 DEBUG(10,("Running [%s]\n", command));
5948 /********* BEGIN SePrintOperatorPrivilege **********/
5950 if ( is_print_op )
5951 become_root();
5953 ret = smbrun(command, NULL);
5955 if ( is_print_op )
5956 unbecome_root();
5958 /********* END SePrintOperatorPrivilege **********/
5960 DEBUGADD(10,("returned [%d]\n", ret));
5962 TALLOC_FREE(command);
5964 if ( ret != 0 ) {
5965 return WERR_ACCESS_DENIED;
5968 return WERR_OK;
5971 /****************************************************************************
5972 ****************************************************************************/
5974 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5976 char *cmd = lp_addprinter_cmd();
5977 char **qlines;
5978 char *command = NULL;
5979 int numlines;
5980 int ret;
5981 int fd;
5982 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5983 bool is_print_op = false;
5984 char *remote_machine = talloc_strdup(ctx, "%m");
5986 if (!remote_machine) {
5987 return false;
5989 remote_machine = talloc_sub_basic(ctx,
5990 current_user_info.smb_name,
5991 current_user_info.domain,
5992 remote_machine);
5993 if (!remote_machine) {
5994 return false;
5997 command = talloc_asprintf(ctx,
5998 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5999 cmd, printer->info_2->printername, printer->info_2->sharename,
6000 printer->info_2->portname, printer->info_2->drivername,
6001 printer->info_2->location, printer->info_2->comment, remote_machine);
6002 if (!command) {
6003 return false;
6006 if ( token )
6007 is_print_op = user_has_privileges( token, &se_printop );
6009 DEBUG(10,("Running [%s]\n", command));
6011 /********* BEGIN SePrintOperatorPrivilege **********/
6013 if ( is_print_op )
6014 become_root();
6016 if ( (ret = smbrun(command, &fd)) == 0 ) {
6017 /* Tell everyone we updated smb.conf. */
6018 message_send_all(smbd_messaging_context(),
6019 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6022 if ( is_print_op )
6023 unbecome_root();
6025 /********* END SePrintOperatorPrivilege **********/
6027 DEBUGADD(10,("returned [%d]\n", ret));
6029 TALLOC_FREE(command);
6030 TALLOC_FREE(remote_machine);
6032 if ( ret != 0 ) {
6033 if (fd != -1)
6034 close(fd);
6035 return false;
6038 /* reload our services immediately */
6039 become_root();
6040 reload_services(false);
6041 unbecome_root();
6043 numlines = 0;
6044 /* Get lines and convert them back to dos-codepage */
6045 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6046 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6047 close(fd);
6049 /* Set the portname to what the script says the portname should be. */
6050 /* but don't require anything to be return from the script exit a good error code */
6052 if (numlines) {
6053 /* Set the portname to what the script says the portname should be. */
6054 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6055 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6058 TALLOC_FREE(qlines);
6059 return true;
6063 /********************************************************************
6064 * Called by spoolss_api_setprinter
6065 * when updating a printer description.
6066 ********************************************************************/
6068 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
6069 struct spoolss_SetPrinterInfoCtr *info_ctr,
6070 struct spoolss_DeviceMode *devmode)
6072 int snum;
6073 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6074 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6075 WERROR result;
6076 UNISTR2 buffer;
6077 fstring asc_buffer;
6079 DEBUG(8,("update_printer\n"));
6081 result = WERR_OK;
6083 if (!Printer) {
6084 result = WERR_BADFID;
6085 goto done;
6088 if (!get_printer_snum(p, handle, &snum, NULL)) {
6089 result = WERR_BADFID;
6090 goto done;
6093 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6094 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6095 result = WERR_BADFID;
6096 goto done;
6099 DEBUGADD(8,("Converting info_2 struct\n"));
6102 * convert_printer_info converts the incoming
6103 * info from the client and overwrites the info
6104 * just read from the tdb in the pointer 'printer'.
6107 if (!convert_printer_info(info_ctr, printer)) {
6108 result = WERR_NOMEM;
6109 goto done;
6112 if (devmode) {
6113 /* we have a valid devmode
6114 convert it and link it*/
6116 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6117 if (!convert_devicemode(printer->info_2->printername, devmode,
6118 &printer->info_2->devmode)) {
6119 result = WERR_NOMEM;
6120 goto done;
6124 /* Do sanity check on the requested changes for Samba */
6126 if (!check_printer_ok(printer->info_2, snum)) {
6127 result = WERR_INVALID_PARAM;
6128 goto done;
6131 /* FIXME!!! If the driver has changed we really should verify that
6132 it is installed before doing much else --jerry */
6134 /* Check calling user has permission to update printer description */
6136 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6137 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6138 result = WERR_ACCESS_DENIED;
6139 goto done;
6142 /* Call addprinter hook */
6143 /* Check changes to see if this is really needed */
6145 if ( *lp_addprinter_cmd()
6146 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6147 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6148 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6149 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6151 /* add_printer_hook() will call reload_services() */
6153 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6154 printer) ) {
6155 result = WERR_ACCESS_DENIED;
6156 goto done;
6161 * When a *new* driver is bound to a printer, the drivername is used to
6162 * lookup previously saved driver initialization info, which is then
6163 * bound to the printer, simulating what happens in the Windows arch.
6165 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6167 if (!set_driver_init(printer, 2))
6169 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6170 printer->info_2->drivername));
6173 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6174 printer->info_2->drivername));
6176 notify_printer_driver(snum, printer->info_2->drivername);
6180 * flag which changes actually occured. This is a small subset of
6181 * all the possible changes. We also have to update things in the
6182 * DsSpooler key.
6185 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6186 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6187 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6188 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6190 notify_printer_comment(snum, printer->info_2->comment);
6193 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6194 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6195 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6196 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6198 notify_printer_sharename(snum, printer->info_2->sharename);
6201 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6202 char *pname;
6204 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6205 pname++;
6206 else
6207 pname = printer->info_2->printername;
6210 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6211 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6212 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6214 notify_printer_printername( snum, pname );
6217 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6218 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6219 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6220 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6222 notify_printer_port(snum, printer->info_2->portname);
6225 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6226 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6227 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6228 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6230 notify_printer_location(snum, printer->info_2->location);
6233 /* here we need to update some more DsSpooler keys */
6234 /* uNCName, serverName, shortServerName */
6236 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6237 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6238 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6239 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6240 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6242 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6243 global_myname(), printer->info_2->sharename );
6244 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6245 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6246 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6248 /* Update printer info */
6249 result = mod_a_printer(printer, 2);
6251 done:
6252 free_a_printer(&printer, 2);
6253 free_a_printer(&old_printer, 2);
6256 return result;
6259 /****************************************************************************
6260 ****************************************************************************/
6261 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6262 struct policy_handle *handle,
6263 struct spoolss_SetPrinterInfo7 *info7)
6265 #ifdef HAVE_ADS
6266 int snum;
6267 Printer_entry *Printer;
6269 if ( lp_security() != SEC_ADS ) {
6270 return WERR_UNKNOWN_LEVEL;
6273 Printer = find_printer_index_by_hnd(p, handle);
6275 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6277 if (!Printer)
6278 return WERR_BADFID;
6280 if (!get_printer_snum(p, handle, &snum, NULL))
6281 return WERR_BADFID;
6283 nt_printer_publish(Printer, snum, info7->action);
6285 return WERR_OK;
6286 #else
6287 return WERR_UNKNOWN_LEVEL;
6288 #endif
6291 /****************************************************************
6292 _spoolss_SetPrinter
6293 ****************************************************************/
6295 WERROR _spoolss_SetPrinter(pipes_struct *p,
6296 struct spoolss_SetPrinter *r)
6298 WERROR result;
6300 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6302 if (!Printer) {
6303 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6304 OUR_HANDLE(r->in.handle)));
6305 return WERR_BADFID;
6308 /* check the level */
6309 switch (r->in.info_ctr->level) {
6310 case 0:
6311 return control_printer(r->in.handle, r->in.command, p);
6312 case 2:
6313 result = update_printer(p, r->in.handle,
6314 r->in.info_ctr,
6315 r->in.devmode_ctr->devmode);
6316 if (!W_ERROR_IS_OK(result))
6317 return result;
6318 if (r->in.secdesc_ctr->sd)
6319 result = update_printer_sec(r->in.handle, p,
6320 r->in.secdesc_ctr);
6321 return result;
6322 case 3:
6323 return update_printer_sec(r->in.handle, p,
6324 r->in.secdesc_ctr);
6325 case 7:
6326 return publish_or_unpublish_printer(p, r->in.handle,
6327 r->in.info_ctr->info.info7);
6328 default:
6329 return WERR_UNKNOWN_LEVEL;
6333 /****************************************************************
6334 _spoolss_FindClosePrinterNotify
6335 ****************************************************************/
6337 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6338 struct spoolss_FindClosePrinterNotify *r)
6340 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6342 if (!Printer) {
6343 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6344 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6345 return WERR_BADFID;
6348 if (Printer->notify.client_connected == true) {
6349 int snum = -1;
6351 if ( Printer->printer_type == SPLHND_SERVER)
6352 snum = -1;
6353 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6354 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6355 return WERR_BADFID;
6357 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6360 Printer->notify.flags=0;
6361 Printer->notify.options=0;
6362 Printer->notify.localmachine[0]='\0';
6363 Printer->notify.printerlocal=0;
6364 TALLOC_FREE(Printer->notify.option);
6365 Printer->notify.client_connected = false;
6367 return WERR_OK;
6370 /****************************************************************
6371 _spoolss_AddJob
6372 ****************************************************************/
6374 WERROR _spoolss_AddJob(pipes_struct *p,
6375 struct spoolss_AddJob *r)
6377 if (!r->in.buffer && (r->in.offered != 0)) {
6378 return WERR_INVALID_PARAM;
6381 /* this is what a NT server returns for AddJob. AddJob must fail on
6382 * non-local printers */
6384 if (r->in.level != 1) {
6385 return WERR_UNKNOWN_LEVEL;
6388 return WERR_INVALID_PARAM;
6391 /****************************************************************************
6392 fill_job_info1
6393 ****************************************************************************/
6395 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6396 struct spoolss_JobInfo1 *r,
6397 const print_queue_struct *queue,
6398 int position, int snum,
6399 const NT_PRINTER_INFO_LEVEL *ntprinter)
6401 struct tm *t;
6403 t = gmtime(&queue->time);
6405 r->job_id = queue->job;
6407 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6408 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6409 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6410 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6411 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6412 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6413 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6414 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6415 r->data_type = talloc_strdup(mem_ctx, "RAW");
6416 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6417 r->text_status = talloc_strdup(mem_ctx, "");
6418 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6420 r->status = nt_printj_status(queue->status);
6421 r->priority = queue->priority;
6422 r->position = position;
6423 r->total_pages = queue->page_count;
6424 r->pages_printed = 0; /* ??? */
6426 init_systemtime(&r->submitted, t);
6428 return WERR_OK;
6431 /****************************************************************************
6432 fill_job_info2
6433 ****************************************************************************/
6435 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6436 struct spoolss_JobInfo2 *r,
6437 const print_queue_struct *queue,
6438 int position, int snum,
6439 const NT_PRINTER_INFO_LEVEL *ntprinter,
6440 struct spoolss_DeviceMode *devmode)
6442 struct tm *t;
6444 t = gmtime(&queue->time);
6446 r->job_id = queue->job;
6448 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6449 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6450 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6451 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6452 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6453 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6454 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6455 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6456 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6457 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6458 r->data_type = talloc_strdup(mem_ctx, "RAW");
6459 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6460 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6461 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6462 r->parameters = talloc_strdup(mem_ctx, "");
6463 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6464 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6465 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6467 r->devmode = devmode;
6469 r->text_status = talloc_strdup(mem_ctx, "");
6470 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6472 r->secdesc = NULL;
6474 r->status = nt_printj_status(queue->status);
6475 r->priority = queue->priority;
6476 r->position = position;
6477 r->start_time = 0;
6478 r->until_time = 0;
6479 r->total_pages = queue->page_count;
6480 r->size = queue->size;
6481 init_systemtime(&r->submitted, t);
6482 r->time = 0;
6483 r->pages_printed = 0; /* ??? */
6485 return WERR_OK;
6488 /****************************************************************************
6489 Enumjobs at level 1.
6490 ****************************************************************************/
6492 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6493 const print_queue_struct *queue,
6494 uint32_t num_queues, int snum,
6495 const NT_PRINTER_INFO_LEVEL *ntprinter,
6496 union spoolss_JobInfo **info_p,
6497 uint32_t *count)
6499 union spoolss_JobInfo *info;
6500 int i;
6501 WERROR result = WERR_OK;
6503 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6504 W_ERROR_HAVE_NO_MEMORY(info);
6506 *count = num_queues;
6508 for (i=0; i<*count; i++) {
6509 result = fill_job_info1(info,
6510 &info[i].info1,
6511 &queue[i],
6513 snum,
6514 ntprinter);
6515 if (!W_ERROR_IS_OK(result)) {
6516 goto out;
6520 out:
6521 if (!W_ERROR_IS_OK(result)) {
6522 TALLOC_FREE(info);
6523 *count = 0;
6524 return result;
6527 *info_p = info;
6529 return WERR_OK;
6532 /****************************************************************************
6533 Enumjobs at level 2.
6534 ****************************************************************************/
6536 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6537 const print_queue_struct *queue,
6538 uint32_t num_queues, int snum,
6539 const NT_PRINTER_INFO_LEVEL *ntprinter,
6540 union spoolss_JobInfo **info_p,
6541 uint32_t *count)
6543 union spoolss_JobInfo *info;
6544 int i;
6545 WERROR result = WERR_OK;
6547 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6548 W_ERROR_HAVE_NO_MEMORY(info);
6550 *count = num_queues;
6552 for (i=0; i<*count; i++) {
6554 struct spoolss_DeviceMode *devmode;
6556 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6557 if (!devmode) {
6558 result = WERR_NOMEM;
6559 goto out;
6562 result = fill_job_info2(info,
6563 &info[i].info2,
6564 &queue[i],
6566 snum,
6567 ntprinter,
6568 devmode);
6569 if (!W_ERROR_IS_OK(result)) {
6570 goto out;
6574 out:
6575 if (!W_ERROR_IS_OK(result)) {
6576 TALLOC_FREE(info);
6577 *count = 0;
6578 return result;
6581 *info_p = info;
6583 return WERR_OK;
6586 /****************************************************************
6587 _spoolss_EnumJobs
6588 ****************************************************************/
6590 WERROR _spoolss_EnumJobs(pipes_struct *p,
6591 struct spoolss_EnumJobs *r)
6593 WERROR result;
6594 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6595 int snum;
6596 print_status_struct prt_status;
6597 print_queue_struct *queue = NULL;
6598 uint32_t count;
6600 /* that's an [in out] buffer */
6602 if (!r->in.buffer && (r->in.offered != 0)) {
6603 return WERR_INVALID_PARAM;
6606 DEBUG(4,("_spoolss_EnumJobs\n"));
6608 *r->out.needed = 0;
6609 *r->out.count = 0;
6610 *r->out.info = NULL;
6612 /* lookup the printer snum and tdb entry */
6614 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6615 return WERR_BADFID;
6618 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6619 if (!W_ERROR_IS_OK(result)) {
6620 return result;
6623 count = print_queue_status(snum, &queue, &prt_status);
6624 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6625 count, prt_status.status, prt_status.message));
6627 if (count == 0) {
6628 SAFE_FREE(queue);
6629 free_a_printer(&ntprinter, 2);
6630 return WERR_OK;
6633 switch (r->in.level) {
6634 case 1:
6635 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6636 ntprinter, r->out.info, r->out.count);
6637 break;
6638 case 2:
6639 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6640 ntprinter, r->out.info, r->out.count);
6641 break;
6642 default:
6643 result = WERR_UNKNOWN_LEVEL;
6644 break;
6647 SAFE_FREE(queue);
6648 free_a_printer(&ntprinter, 2);
6650 if (!W_ERROR_IS_OK(result)) {
6651 return result;
6654 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6655 spoolss_EnumJobs, NULL,
6656 *r->out.info, r->in.level,
6657 *r->out.count);
6658 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6659 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6661 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6664 /****************************************************************
6665 _spoolss_ScheduleJob
6666 ****************************************************************/
6668 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6669 struct spoolss_ScheduleJob *r)
6671 return WERR_OK;
6674 /****************************************************************
6675 _spoolss_SetJob
6676 ****************************************************************/
6678 WERROR _spoolss_SetJob(pipes_struct *p,
6679 struct spoolss_SetJob *r)
6681 int snum;
6682 WERROR errcode = WERR_BADFUNC;
6684 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6685 return WERR_BADFID;
6688 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6689 return WERR_INVALID_PRINTER_NAME;
6692 switch (r->in.command) {
6693 case SPOOLSS_JOB_CONTROL_CANCEL:
6694 case SPOOLSS_JOB_CONTROL_DELETE:
6695 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6696 errcode = WERR_OK;
6698 break;
6699 case SPOOLSS_JOB_CONTROL_PAUSE:
6700 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6701 errcode = WERR_OK;
6703 break;
6704 case SPOOLSS_JOB_CONTROL_RESTART:
6705 case SPOOLSS_JOB_CONTROL_RESUME:
6706 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6707 errcode = WERR_OK;
6709 break;
6710 default:
6711 return WERR_UNKNOWN_LEVEL;
6714 return errcode;
6717 static const struct print_architecture_table_node archi_table[]= {
6719 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
6720 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
6721 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
6722 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
6723 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
6724 {"Windows IA64", SPL_ARCH_IA64, 3 },
6725 {"Windows x64", SPL_ARCH_X64, 3 },
6726 {NULL, "", -1 }
6729 /****************************************************************************
6730 Enumerates all printer drivers by level and architecture.
6731 ****************************************************************************/
6733 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6734 const char *servername,
6735 const char *architecture,
6736 uint32_t level,
6737 union spoolss_DriverInfo **info_p,
6738 uint32_t *count_p)
6740 int i;
6741 int ndrivers;
6742 uint32_t version;
6743 fstring *list = NULL;
6744 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6745 union spoolss_DriverInfo *info = NULL;
6746 uint32_t count = 0;
6747 WERROR result = WERR_OK;
6749 *count_p = 0;
6750 *info_p = NULL;
6752 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6753 list = NULL;
6754 ndrivers = get_ntdrivers(&list, architecture, version);
6755 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6756 ndrivers, architecture, version));
6758 if (ndrivers == -1) {
6759 result = WERR_NOMEM;
6760 goto out;
6763 if (ndrivers != 0) {
6764 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6765 union spoolss_DriverInfo,
6766 count + ndrivers);
6767 if (!info) {
6768 DEBUG(0,("enumprinterdrivers_level1: "
6769 "failed to enlarge driver info buffer!\n"));
6770 result = WERR_NOMEM;
6771 goto out;
6775 for (i=0; i<ndrivers; i++) {
6776 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6777 ZERO_STRUCT(driver);
6778 result = get_a_printer_driver(&driver, 3, list[i],
6779 architecture, version);
6780 if (!W_ERROR_IS_OK(result)) {
6781 goto out;
6784 switch (level) {
6785 case 1:
6786 result = fill_printer_driver_info1(info, &info[count+i].info1,
6787 &driver, servername,
6788 architecture);
6789 break;
6790 case 2:
6791 result = fill_printer_driver_info2(info, &info[count+i].info2,
6792 &driver, servername);
6793 break;
6794 case 3:
6795 result = fill_printer_driver_info3(info, &info[count+i].info3,
6796 &driver, servername);
6797 break;
6798 case 4:
6799 result = fill_printer_driver_info4(info, &info[count+i].info4,
6800 &driver, servername);
6801 break;
6802 case 5:
6803 result = fill_printer_driver_info5(info, &info[count+i].info5,
6804 &driver, servername);
6805 break;
6806 case 6:
6807 result = fill_printer_driver_info6(info, &info[count+i].info6,
6808 &driver, servername);
6809 break;
6810 default:
6811 result = WERR_UNKNOWN_LEVEL;
6812 break;
6815 if (!W_ERROR_IS_OK(result)) {
6816 free_a_printer_driver(driver, 3);
6817 goto out;
6819 free_a_printer_driver(driver, 3);
6822 count += ndrivers;
6823 SAFE_FREE(list);
6826 out:
6827 SAFE_FREE(list);
6829 if (!W_ERROR_IS_OK(result)) {
6830 TALLOC_FREE(info);
6831 return result;
6834 *info_p = info;
6835 *count_p = count;
6837 return WERR_OK;
6840 /****************************************************************************
6841 Enumerates all printer drivers by level.
6842 ****************************************************************************/
6844 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6845 const char *servername,
6846 const char *architecture,
6847 uint32_t level,
6848 union spoolss_DriverInfo **info_p,
6849 uint32_t *count_p)
6851 uint32_t a,i;
6852 WERROR result = WERR_OK;
6854 if (strequal(architecture, "all")) {
6856 for (a=0; archi_table[a].long_archi != NULL; a++) {
6858 union spoolss_DriverInfo *info = NULL;
6859 uint32_t count = 0;
6861 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6862 servername,
6863 archi_table[a].long_archi,
6864 level,
6865 &info,
6866 &count);
6867 if (!W_ERROR_IS_OK(result)) {
6868 continue;
6871 for (i=0; i < count; i++) {
6872 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6873 info[i], info_p, count_p);
6877 return result;
6880 return enumprinterdrivers_level_by_architecture(mem_ctx,
6881 servername,
6882 architecture,
6883 level,
6884 info_p,
6885 count_p);
6888 /****************************************************************************
6889 Enumerates all printer drivers at level 1.
6890 ****************************************************************************/
6892 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6893 const char *servername,
6894 const char *architecture,
6895 union spoolss_DriverInfo **info_p,
6896 uint32_t *count)
6898 return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6899 info_p, count);
6902 /****************************************************************************
6903 Enumerates all printer drivers at level 2.
6904 ****************************************************************************/
6906 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6907 const char *servername,
6908 const char *architecture,
6909 union spoolss_DriverInfo **info_p,
6910 uint32_t *count)
6912 return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6913 info_p, count);
6916 /****************************************************************************
6917 Enumerates all printer drivers at level 3.
6918 ****************************************************************************/
6920 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6921 const char *servername,
6922 const char *architecture,
6923 union spoolss_DriverInfo **info_p,
6924 uint32_t *count)
6926 return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6927 info_p, count);
6930 /****************************************************************************
6931 Enumerates all printer drivers at level 4.
6932 ****************************************************************************/
6934 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6935 const char *servername,
6936 const char *architecture,
6937 union spoolss_DriverInfo **info_p,
6938 uint32_t *count)
6940 return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6941 info_p, count);
6944 /****************************************************************************
6945 Enumerates all printer drivers at level 5.
6946 ****************************************************************************/
6948 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6949 const char *servername,
6950 const char *architecture,
6951 union spoolss_DriverInfo **info_p,
6952 uint32_t *count)
6954 return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6955 info_p, count);
6958 /****************************************************************************
6959 Enumerates all printer drivers at level 6.
6960 ****************************************************************************/
6962 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6963 const char *servername,
6964 const char *architecture,
6965 union spoolss_DriverInfo **info_p,
6966 uint32_t *count)
6968 return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6969 info_p, count);
6973 /****************************************************************
6974 _spoolss_EnumPrinterDrivers
6975 ****************************************************************/
6977 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6978 struct spoolss_EnumPrinterDrivers *r)
6980 const char *cservername;
6981 WERROR result;
6983 /* that's an [in out] buffer */
6985 if (!r->in.buffer && (r->in.offered != 0)) {
6986 return WERR_INVALID_PARAM;
6989 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6991 *r->out.needed = 0;
6992 *r->out.count = 0;
6993 *r->out.info = NULL;
6995 cservername = canon_servername(r->in.server);
6997 if (!is_myname_or_ipaddr(cservername)) {
6998 return WERR_UNKNOWN_PRINTER_DRIVER;
7001 switch (r->in.level) {
7002 case 1:
7003 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
7004 r->in.environment,
7005 r->out.info, r->out.count);
7006 break;
7007 case 2:
7008 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
7009 r->in.environment,
7010 r->out.info, r->out.count);
7011 break;
7012 case 3:
7013 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
7014 r->in.environment,
7015 r->out.info, r->out.count);
7016 break;
7017 case 4:
7018 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
7019 r->in.environment,
7020 r->out.info, r->out.count);
7021 break;
7022 case 5:
7023 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
7024 r->in.environment,
7025 r->out.info, r->out.count);
7026 break;
7027 case 6:
7028 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
7029 r->in.environment,
7030 r->out.info, r->out.count);
7031 break;
7032 default:
7033 return WERR_UNKNOWN_LEVEL;
7036 if (!W_ERROR_IS_OK(result)) {
7037 return result;
7040 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7041 spoolss_EnumPrinterDrivers, NULL,
7042 *r->out.info, r->in.level,
7043 *r->out.count);
7044 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7045 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7047 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7050 /****************************************************************************
7051 ****************************************************************************/
7053 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7054 struct spoolss_FormInfo1 *r,
7055 const nt_forms_struct *form)
7057 r->form_name = talloc_strdup(mem_ctx, form->name);
7058 W_ERROR_HAVE_NO_MEMORY(r->form_name);
7060 r->flags = form->flag;
7061 r->size.width = form->width;
7062 r->size.height = form->length;
7063 r->area.left = form->left;
7064 r->area.top = form->top;
7065 r->area.right = form->right;
7066 r->area.bottom = form->bottom;
7068 return WERR_OK;
7071 /****************************************************************
7072 spoolss_enumforms_level1
7073 ****************************************************************/
7075 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7076 const nt_forms_struct *builtin_forms,
7077 uint32_t num_builtin_forms,
7078 const nt_forms_struct *user_forms,
7079 uint32_t num_user_forms,
7080 union spoolss_FormInfo **info_p,
7081 uint32_t *count)
7083 union spoolss_FormInfo *info;
7084 WERROR result = WERR_OK;
7085 int i;
7087 *count = num_builtin_forms + num_user_forms;
7089 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7090 W_ERROR_HAVE_NO_MEMORY(info);
7092 /* construct the list of form structures */
7093 for (i=0; i<num_builtin_forms; i++) {
7094 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
7095 result = fill_form_info_1(info, &info[i].info1,
7096 &builtin_forms[i]);
7097 if (!W_ERROR_IS_OK(result)) {
7098 goto out;
7102 for (i=0; i<num_user_forms; i++) {
7103 DEBUGADD(6,("Filling user form number [%d]\n",i));
7104 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
7105 &user_forms[i]);
7106 if (!W_ERROR_IS_OK(result)) {
7107 goto out;
7111 out:
7112 if (!W_ERROR_IS_OK(result)) {
7113 TALLOC_FREE(info);
7114 *count = 0;
7115 return result;
7118 *info_p = info;
7120 return WERR_OK;
7123 /****************************************************************
7124 _spoolss_EnumForms
7125 ****************************************************************/
7127 WERROR _spoolss_EnumForms(pipes_struct *p,
7128 struct spoolss_EnumForms *r)
7130 WERROR result;
7131 nt_forms_struct *user_forms = NULL;
7132 nt_forms_struct *builtin_forms = NULL;
7133 uint32_t num_user_forms;
7134 uint32_t num_builtin_forms;
7136 *r->out.count = 0;
7137 *r->out.needed = 0;
7138 *r->out.info = NULL;
7140 /* that's an [in out] buffer */
7142 if (!r->in.buffer && (r->in.offered != 0) ) {
7143 return WERR_INVALID_PARAM;
7146 DEBUG(4,("_spoolss_EnumForms\n"));
7147 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7148 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7150 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7151 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7152 num_user_forms = get_ntforms(&user_forms);
7153 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7155 if (num_user_forms + num_builtin_forms == 0) {
7156 SAFE_FREE(builtin_forms);
7157 SAFE_FREE(user_forms);
7158 return WERR_NO_MORE_ITEMS;
7161 switch (r->in.level) {
7162 case 1:
7163 result = spoolss_enumforms_level1(p->mem_ctx,
7164 builtin_forms,
7165 num_builtin_forms,
7166 user_forms,
7167 num_user_forms,
7168 r->out.info,
7169 r->out.count);
7170 break;
7171 default:
7172 result = WERR_UNKNOWN_LEVEL;
7173 break;
7176 SAFE_FREE(user_forms);
7177 SAFE_FREE(builtin_forms);
7179 if (!W_ERROR_IS_OK(result)) {
7180 return result;
7183 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7184 spoolss_EnumForms, NULL,
7185 *r->out.info, r->in.level,
7186 *r->out.count);
7187 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7188 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7190 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7193 /****************************************************************
7194 ****************************************************************/
7196 static WERROR find_form_byname(const char *name,
7197 nt_forms_struct *form)
7199 nt_forms_struct *list = NULL;
7200 int num_forms = 0, i = 0;
7202 if (get_a_builtin_ntform_by_string(name, form)) {
7203 return WERR_OK;
7206 num_forms = get_ntforms(&list);
7207 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7209 if (num_forms == 0) {
7210 return WERR_BADFID;
7213 /* Check if the requested name is in the list of form structures */
7214 for (i = 0; i < num_forms; i++) {
7216 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7218 if (strequal(name, list[i].name)) {
7219 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7220 *form = list[i];
7221 SAFE_FREE(list);
7222 return WERR_OK;
7226 SAFE_FREE(list);
7228 return WERR_BADFID;
7231 /****************************************************************
7232 _spoolss_GetForm
7233 ****************************************************************/
7235 WERROR _spoolss_GetForm(pipes_struct *p,
7236 struct spoolss_GetForm *r)
7238 WERROR result;
7239 nt_forms_struct form;
7241 /* that's an [in out] buffer */
7243 if (!r->in.buffer && (r->in.offered != 0)) {
7244 return WERR_INVALID_PARAM;
7247 DEBUG(4,("_spoolss_GetForm\n"));
7248 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7249 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7251 result = find_form_byname(r->in.form_name, &form);
7252 if (!W_ERROR_IS_OK(result)) {
7253 TALLOC_FREE(r->out.info);
7254 return result;
7257 switch (r->in.level) {
7258 case 1:
7259 result = fill_form_info_1(p->mem_ctx,
7260 &r->out.info->info1,
7261 &form);
7262 break;
7264 default:
7265 result = WERR_UNKNOWN_LEVEL;
7266 break;
7269 if (!W_ERROR_IS_OK(result)) {
7270 TALLOC_FREE(r->out.info);
7271 return result;
7274 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7275 r->out.info, r->in.level);
7276 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7278 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7281 /****************************************************************************
7282 ****************************************************************************/
7284 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7285 struct spoolss_PortInfo1 *r,
7286 const char *name)
7288 r->port_name = talloc_strdup(mem_ctx, name);
7289 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7291 return WERR_OK;
7294 /****************************************************************************
7295 TODO: This probably needs distinguish between TCP/IP and Local ports
7296 somehow.
7297 ****************************************************************************/
7299 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7300 struct spoolss_PortInfo2 *r,
7301 const char *name)
7303 r->port_name = talloc_strdup(mem_ctx, name);
7304 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7306 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7307 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7309 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7310 W_ERROR_HAVE_NO_MEMORY(r->description);
7312 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7313 r->reserved = 0;
7315 return WERR_OK;
7319 /****************************************************************************
7320 wrapper around the enumer ports command
7321 ****************************************************************************/
7323 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7325 char *cmd = lp_enumports_cmd();
7326 char **qlines = NULL;
7327 char *command = NULL;
7328 int numlines;
7329 int ret;
7330 int fd;
7332 *count = 0;
7333 *lines = NULL;
7335 /* if no hook then just fill in the default port */
7337 if ( !*cmd ) {
7338 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7339 return WERR_NOMEM;
7341 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7342 TALLOC_FREE(qlines);
7343 return WERR_NOMEM;
7345 qlines[1] = NULL;
7346 numlines = 1;
7348 else {
7349 /* we have a valid enumport command */
7351 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7352 if (!command) {
7353 return WERR_NOMEM;
7356 DEBUG(10,("Running [%s]\n", command));
7357 ret = smbrun(command, &fd);
7358 DEBUG(10,("Returned [%d]\n", ret));
7359 TALLOC_FREE(command);
7360 if (ret != 0) {
7361 if (fd != -1) {
7362 close(fd);
7364 return WERR_ACCESS_DENIED;
7367 numlines = 0;
7368 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7369 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7370 close(fd);
7373 *count = numlines;
7374 *lines = qlines;
7376 return WERR_OK;
7379 /****************************************************************************
7380 enumports level 1.
7381 ****************************************************************************/
7383 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7384 union spoolss_PortInfo **info_p,
7385 uint32_t *count)
7387 union spoolss_PortInfo *info = NULL;
7388 int i=0;
7389 WERROR result = WERR_OK;
7390 char **qlines = NULL;
7391 int numlines = 0;
7393 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7394 if (!W_ERROR_IS_OK(result)) {
7395 goto out;
7398 if (numlines) {
7399 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7400 if (!info) {
7401 DEBUG(10,("Returning WERR_NOMEM\n"));
7402 result = WERR_NOMEM;
7403 goto out;
7406 for (i=0; i<numlines; i++) {
7407 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7408 result = fill_port_1(info, &info[i].info1, qlines[i]);
7409 if (!W_ERROR_IS_OK(result)) {
7410 goto out;
7414 TALLOC_FREE(qlines);
7416 out:
7417 if (!W_ERROR_IS_OK(result)) {
7418 TALLOC_FREE(info);
7419 TALLOC_FREE(qlines);
7420 *count = 0;
7421 *info_p = NULL;
7422 return result;
7425 *info_p = info;
7426 *count = numlines;
7428 return WERR_OK;
7431 /****************************************************************************
7432 enumports level 2.
7433 ****************************************************************************/
7435 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7436 union spoolss_PortInfo **info_p,
7437 uint32_t *count)
7439 union spoolss_PortInfo *info = NULL;
7440 int i=0;
7441 WERROR result = WERR_OK;
7442 char **qlines = NULL;
7443 int numlines = 0;
7445 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7446 if (!W_ERROR_IS_OK(result)) {
7447 goto out;
7450 if (numlines) {
7451 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7452 if (!info) {
7453 DEBUG(10,("Returning WERR_NOMEM\n"));
7454 result = WERR_NOMEM;
7455 goto out;
7458 for (i=0; i<numlines; i++) {
7459 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7460 result = fill_port_2(info, &info[i].info2, qlines[i]);
7461 if (!W_ERROR_IS_OK(result)) {
7462 goto out;
7466 TALLOC_FREE(qlines);
7468 out:
7469 if (!W_ERROR_IS_OK(result)) {
7470 TALLOC_FREE(info);
7471 TALLOC_FREE(qlines);
7472 *count = 0;
7473 *info_p = NULL;
7474 return result;
7477 *info_p = info;
7478 *count = numlines;
7480 return WERR_OK;
7483 /****************************************************************
7484 _spoolss_EnumPorts
7485 ****************************************************************/
7487 WERROR _spoolss_EnumPorts(pipes_struct *p,
7488 struct spoolss_EnumPorts *r)
7490 WERROR result;
7492 /* that's an [in out] buffer */
7494 if (!r->in.buffer && (r->in.offered != 0)) {
7495 return WERR_INVALID_PARAM;
7498 DEBUG(4,("_spoolss_EnumPorts\n"));
7500 *r->out.count = 0;
7501 *r->out.needed = 0;
7502 *r->out.info = NULL;
7504 switch (r->in.level) {
7505 case 1:
7506 result = enumports_level_1(p->mem_ctx, r->out.info,
7507 r->out.count);
7508 break;
7509 case 2:
7510 result = enumports_level_2(p->mem_ctx, r->out.info,
7511 r->out.count);
7512 break;
7513 default:
7514 return WERR_UNKNOWN_LEVEL;
7517 if (!W_ERROR_IS_OK(result)) {
7518 return result;
7521 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7522 spoolss_EnumPorts, NULL,
7523 *r->out.info, r->in.level,
7524 *r->out.count);
7525 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7526 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7528 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7531 /****************************************************************************
7532 ****************************************************************************/
7534 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7535 const char *server,
7536 struct spoolss_SetPrinterInfoCtr *info_ctr,
7537 struct spoolss_DeviceMode *devmode,
7538 struct security_descriptor *sec_desc,
7539 struct spoolss_UserLevelCtr *user_ctr,
7540 struct policy_handle *handle)
7542 NT_PRINTER_INFO_LEVEL *printer = NULL;
7543 fstring name;
7544 int snum;
7545 WERROR err = WERR_OK;
7547 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7548 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7549 return WERR_NOMEM;
7552 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7553 if (!convert_printer_info(info_ctr, printer)) {
7554 free_a_printer(&printer, 2);
7555 return WERR_NOMEM;
7558 /* check to see if the printer already exists */
7560 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7561 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7562 printer->info_2->sharename));
7563 free_a_printer(&printer, 2);
7564 return WERR_PRINTER_ALREADY_EXISTS;
7567 /* FIXME!!! smbd should check to see if the driver is installed before
7568 trying to add a printer like this --jerry */
7570 if (*lp_addprinter_cmd() ) {
7571 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7572 printer) ) {
7573 free_a_printer(&printer,2);
7574 return WERR_ACCESS_DENIED;
7576 } else {
7577 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7578 "smb.conf parameter \"addprinter command\" is defined. This"
7579 "parameter must exist for this call to succeed\n",
7580 printer->info_2->sharename ));
7583 /* use our primary netbios name since get_a_printer() will convert
7584 it to what the client expects on a case by case basis */
7586 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7587 printer->info_2->sharename);
7590 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7591 free_a_printer(&printer,2);
7592 return WERR_ACCESS_DENIED;
7595 /* you must be a printer admin to add a new printer */
7596 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7597 free_a_printer(&printer,2);
7598 return WERR_ACCESS_DENIED;
7602 * Do sanity check on the requested changes for Samba.
7605 if (!check_printer_ok(printer->info_2, snum)) {
7606 free_a_printer(&printer,2);
7607 return WERR_INVALID_PARAM;
7611 * When a printer is created, the drivername bound to the printer is used
7612 * to lookup previously saved driver initialization info, which is then
7613 * bound to the new printer, simulating what happens in the Windows arch.
7616 if (!devmode)
7618 set_driver_init(printer, 2);
7620 else
7622 /* A valid devmode was included, convert and link it
7624 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7626 if (!convert_devicemode(printer->info_2->printername, devmode,
7627 &printer->info_2->devmode)) {
7628 return WERR_NOMEM;
7632 /* write the ASCII on disk */
7633 err = mod_a_printer(printer, 2);
7634 if (!W_ERROR_IS_OK(err)) {
7635 free_a_printer(&printer,2);
7636 return err;
7639 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7640 /* Handle open failed - remove addition. */
7641 del_a_printer(printer->info_2->sharename);
7642 free_a_printer(&printer,2);
7643 ZERO_STRUCTP(handle);
7644 return WERR_ACCESS_DENIED;
7647 update_c_setprinter(false);
7648 free_a_printer(&printer,2);
7650 return WERR_OK;
7653 /****************************************************************
7654 _spoolss_AddPrinterEx
7655 ****************************************************************/
7657 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7658 struct spoolss_AddPrinterEx *r)
7660 switch (r->in.info_ctr->level) {
7661 case 1:
7662 /* we don't handle yet */
7663 /* but I know what to do ... */
7664 return WERR_UNKNOWN_LEVEL;
7665 case 2:
7666 return spoolss_addprinterex_level_2(p, r->in.server,
7667 r->in.info_ctr,
7668 r->in.devmode_ctr->devmode,
7669 r->in.secdesc_ctr->sd,
7670 r->in.userlevel_ctr,
7671 r->out.handle);
7672 default:
7673 return WERR_UNKNOWN_LEVEL;
7677 /****************************************************************
7678 _spoolss_AddPrinter
7679 ****************************************************************/
7681 WERROR _spoolss_AddPrinter(pipes_struct *p,
7682 struct spoolss_AddPrinter *r)
7684 struct spoolss_AddPrinterEx a;
7685 struct spoolss_UserLevelCtr userlevel_ctr;
7687 ZERO_STRUCT(userlevel_ctr);
7689 userlevel_ctr.level = 1;
7691 a.in.server = r->in.server;
7692 a.in.info_ctr = r->in.info_ctr;
7693 a.in.devmode_ctr = r->in.devmode_ctr;
7694 a.in.secdesc_ctr = r->in.secdesc_ctr;
7695 a.in.userlevel_ctr = &userlevel_ctr;
7696 a.out.handle = r->out.handle;
7698 return _spoolss_AddPrinterEx(p, &a);
7701 /****************************************************************
7702 _spoolss_AddPrinterDriver
7703 ****************************************************************/
7705 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7706 struct spoolss_AddPrinterDriver *r)
7708 uint32_t level = r->in.info_ctr->level;
7709 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7710 WERROR err = WERR_OK;
7711 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7712 const char *driver_name = NULL;
7713 uint32_t version;
7714 const char *fn;
7716 switch (p->hdr_req.opnum) {
7717 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7718 fn = "_spoolss_AddPrinterDriver";
7719 break;
7720 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7721 fn = "_spoolss_AddPrinterDriverEx";
7722 break;
7723 default:
7724 return WERR_INVALID_PARAM;
7728 /* FIXME */
7729 if (level != 3 && level != 6) {
7730 /* Clever hack from Martin Zielinski <mz@seh.de>
7731 * to allow downgrade from level 8 (Vista).
7733 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7734 return WERR_UNKNOWN_LEVEL;
7737 ZERO_STRUCT(driver);
7739 if (!convert_printer_driver_info(info, &driver, level)) {
7740 err = WERR_NOMEM;
7741 goto done;
7744 DEBUG(5,("Cleaning driver's information\n"));
7745 err = clean_up_driver_struct(p, driver, level);
7746 if (!W_ERROR_IS_OK(err))
7747 goto done;
7749 DEBUG(5,("Moving driver to final destination\n"));
7750 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7751 &err)) ) {
7752 goto done;
7755 if (add_a_printer_driver(driver, level)!=0) {
7756 err = WERR_ACCESS_DENIED;
7757 goto done;
7760 switch(level) {
7761 case 3:
7762 driver_name = driver.info_3->name ? driver.info_3->name : "";
7763 break;
7764 case 6:
7765 driver_name = driver.info_6->name ? driver.info_6->name : "";
7766 break;
7770 * I think this is where he DrvUpgradePrinter() hook would be
7771 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7772 * server. Right now, we just need to send ourselves a message
7773 * to update each printer bound to this driver. --jerry
7776 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7777 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7778 fn, driver_name));
7782 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7783 * decide if the driver init data should be deleted. The rules are:
7784 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7785 * 2) delete init data only if there is no 2k/Xp driver
7786 * 3) always delete init data
7787 * The generalized rule is always use init data from the highest order driver.
7788 * It is necessary to follow the driver install by an initialization step to
7789 * finish off this process.
7791 if (level == 3)
7792 version = driver.info_3->cversion;
7793 else if (level == 6)
7794 version = driver.info_6->version;
7795 else
7796 version = -1;
7797 switch (version) {
7799 * 9x printer driver - never delete init data
7801 case 0:
7802 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7803 fn, driver_name));
7804 break;
7807 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7808 * there is no 2k/Xp driver init data for this driver name.
7810 case 2:
7812 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7814 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7816 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7818 if (!del_driver_init(driver_name))
7819 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7820 fn, driver_name));
7821 } else {
7823 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7825 free_a_printer_driver(driver1,3);
7826 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7827 fn, driver_name));
7830 break;
7833 * 2k or Xp printer driver - always delete init data
7835 case 3:
7836 if (!del_driver_init(driver_name))
7837 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7838 fn, driver_name));
7839 break;
7841 default:
7842 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7843 break;
7847 done:
7848 free_a_printer_driver(driver, level);
7849 return err;
7852 /****************************************************************
7853 _spoolss_AddPrinterDriverEx
7854 ****************************************************************/
7856 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7857 struct spoolss_AddPrinterDriverEx *r)
7859 struct spoolss_AddPrinterDriver a;
7862 * we only support the semantics of AddPrinterDriver()
7863 * i.e. only copy files that are newer than existing ones
7866 if (r->in.flags != APD_COPY_NEW_FILES) {
7867 return WERR_ACCESS_DENIED;
7870 a.in.servername = r->in.servername;
7871 a.in.info_ctr = r->in.info_ctr;
7873 return _spoolss_AddPrinterDriver(p, &a);
7876 /****************************************************************************
7877 ****************************************************************************/
7879 struct _spoolss_paths {
7880 int type;
7881 const char *share;
7882 const char *dir;
7885 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7887 static const struct _spoolss_paths spoolss_paths[]= {
7888 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7889 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7892 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7893 const char *servername,
7894 const char *environment,
7895 int component,
7896 char **path)
7898 const char *pservername = NULL;
7899 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7900 const char *short_archi;
7902 *path = NULL;
7904 /* environment may be empty */
7905 if (environment && strlen(environment)) {
7906 long_archi = environment;
7909 /* servername may be empty */
7910 if (servername && strlen(servername)) {
7911 pservername = canon_servername(servername);
7913 if (!is_myname_or_ipaddr(pservername)) {
7914 return WERR_INVALID_PARAM;
7918 if (!(short_archi = get_short_archi(long_archi))) {
7919 return WERR_INVALID_ENVIRONMENT;
7922 switch (component) {
7923 case SPOOLSS_PRTPROCS_PATH:
7924 case SPOOLSS_DRIVER_PATH:
7925 if (pservername) {
7926 *path = talloc_asprintf(mem_ctx,
7927 "\\\\%s\\%s\\%s",
7928 pservername,
7929 spoolss_paths[component].share,
7930 short_archi);
7931 } else {
7932 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7933 SPOOLSS_DEFAULT_SERVER_PATH,
7934 spoolss_paths[component].dir,
7935 short_archi);
7937 break;
7938 default:
7939 return WERR_INVALID_PARAM;
7942 if (!*path) {
7943 return WERR_NOMEM;
7946 return WERR_OK;
7949 /****************************************************************************
7950 ****************************************************************************/
7952 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7953 const char *servername,
7954 const char *environment,
7955 struct spoolss_DriverDirectoryInfo1 *r)
7957 WERROR werr;
7958 char *path = NULL;
7960 werr = compose_spoolss_server_path(mem_ctx,
7961 servername,
7962 environment,
7963 SPOOLSS_DRIVER_PATH,
7964 &path);
7965 if (!W_ERROR_IS_OK(werr)) {
7966 return werr;
7969 DEBUG(4,("printer driver directory: [%s]\n", path));
7971 r->directory_name = path;
7973 return WERR_OK;
7976 /****************************************************************
7977 _spoolss_GetPrinterDriverDirectory
7978 ****************************************************************/
7980 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7981 struct spoolss_GetPrinterDriverDirectory *r)
7983 WERROR werror;
7985 /* that's an [in out] buffer */
7987 if (!r->in.buffer && (r->in.offered != 0)) {
7988 return WERR_INVALID_PARAM;
7991 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7992 r->in.level));
7994 *r->out.needed = 0;
7996 /* r->in.level is ignored */
7998 werror = getprinterdriverdir_level_1(p->mem_ctx,
7999 r->in.server,
8000 r->in.environment,
8001 &r->out.info->info1);
8002 if (!W_ERROR_IS_OK(werror)) {
8003 TALLOC_FREE(r->out.info);
8004 return werror;
8007 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
8008 r->out.info, r->in.level);
8009 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8011 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8014 /****************************************************************
8015 _spoolss_EnumPrinterData
8016 ****************************************************************/
8018 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
8019 struct spoolss_EnumPrinterData *r)
8021 NT_PRINTER_INFO_LEVEL *printer = NULL;
8022 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8023 int snum;
8024 WERROR result;
8025 struct regval_blob *val = NULL;
8026 NT_PRINTER_DATA *p_data;
8027 int i, key_index, num_values;
8028 int name_length;
8030 *r->out.value_needed = 0;
8031 *r->out.type = REG_NONE;
8032 *r->out.data_needed = 0;
8034 DEBUG(5,("_spoolss_EnumPrinterData\n"));
8036 if (!Printer) {
8037 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
8038 OUR_HANDLE(r->in.handle)));
8039 return WERR_BADFID;
8042 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8043 return WERR_BADFID;
8046 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8047 if (!W_ERROR_IS_OK(result)) {
8048 return result;
8051 p_data = printer->info_2->data;
8052 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8054 result = WERR_OK;
8057 * The NT machine wants to know the biggest size of value and data
8059 * cf: MSDN EnumPrinterData remark section
8062 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
8064 uint32_t biggest_valuesize = 0;
8065 uint32_t biggest_datasize = 0;
8067 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8069 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8071 for ( i=0; i<num_values; i++ )
8073 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8075 name_length = strlen(val->valuename);
8076 if ( strlen(val->valuename) > biggest_valuesize )
8077 biggest_valuesize = name_length;
8079 if ( val->size > biggest_datasize )
8080 biggest_datasize = val->size;
8082 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8083 biggest_datasize));
8086 /* the value is an UNICODE string but real_value_size is the length
8087 in bytes including the trailing 0 */
8089 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8090 *r->out.data_needed = biggest_datasize;
8092 DEBUG(6,("final values: [%d], [%d]\n",
8093 *r->out.value_needed, *r->out.data_needed));
8095 goto done;
8099 * the value len is wrong in NT sp3
8100 * that's the number of bytes not the number of unicode chars
8103 if (key_index != -1) {
8104 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8105 r->in.enum_index);
8108 if (!val) {
8110 /* out_value should default to "" or else NT4 has
8111 problems unmarshalling the response */
8113 if (r->in.value_offered) {
8114 *r->out.value_needed = 1;
8115 r->out.value_name = talloc_strdup(r, "");
8116 if (!r->out.value_name) {
8117 result = WERR_NOMEM;
8118 goto done;
8120 } else {
8121 r->out.value_name = NULL;
8122 *r->out.value_needed = 0;
8125 /* the data is counted in bytes */
8127 *r->out.data_needed = r->in.data_offered;
8129 result = WERR_NO_MORE_ITEMS;
8130 } else {
8132 * the value is:
8133 * - counted in bytes in the request
8134 * - counted in UNICODE chars in the max reply
8135 * - counted in bytes in the real size
8137 * take a pause *before* coding not *during* coding
8140 /* name */
8141 if (r->in.value_offered) {
8142 r->out.value_name = talloc_strdup(r, regval_name(val));
8143 if (!r->out.value_name) {
8144 result = WERR_NOMEM;
8145 goto done;
8147 *r->out.value_needed = strlen_m(regval_name(val));
8148 } else {
8149 r->out.value_name = NULL;
8150 *r->out.value_needed = 0;
8153 /* type */
8155 *r->out.type = regval_type(val);
8157 /* data - counted in bytes */
8159 if (r->out.data && regval_size(val)) {
8160 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8163 *r->out.data_needed = regval_size(val);
8166 done:
8167 free_a_printer(&printer, 2);
8168 return result;
8171 /****************************************************************
8172 _spoolss_SetPrinterData
8173 ****************************************************************/
8175 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8176 struct spoolss_SetPrinterData *r)
8178 NT_PRINTER_INFO_LEVEL *printer = NULL;
8179 int snum=0;
8180 WERROR result = WERR_OK;
8181 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8182 DATA_BLOB blob;
8184 DEBUG(5,("_spoolss_SetPrinterData\n"));
8186 if (!Printer) {
8187 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8188 OUR_HANDLE(r->in.handle)));
8189 return WERR_BADFID;
8192 if (Printer->printer_type == SPLHND_SERVER) {
8193 DEBUG(10,("_spoolss_SetPrinterData: "
8194 "Not implemented for server handles yet\n"));
8195 return WERR_INVALID_PARAM;
8198 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8199 return WERR_BADFID;
8203 * Access check : NT returns "access denied" if you make a
8204 * SetPrinterData call without the necessary privildge.
8205 * we were originally returning OK if nothing changed
8206 * which made Win2k issue **a lot** of SetPrinterData
8207 * when connecting to a printer --jerry
8210 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8211 DEBUG(3,("_spoolss_SetPrinterData: "
8212 "change denied by handle access permissions\n"));
8213 result = WERR_ACCESS_DENIED;
8214 goto done;
8217 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8218 if (!W_ERROR_IS_OK(result)) {
8219 return result;
8222 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8223 r->in.type, &r->in.data);
8224 if (!W_ERROR_IS_OK(result)) {
8225 goto done;
8229 * When client side code sets a magic printer data key, detect it and save
8230 * the current printer data and the magic key's data (its the DEVMODE) for
8231 * future printer/driver initializations.
8233 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8234 /* Set devmode and printer initialization info */
8235 result = save_driver_init(printer, 2, blob.data, blob.length);
8237 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8239 goto done;
8242 result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8243 r->in.value_name, r->in.type,
8244 blob.data, blob.length);
8245 if (W_ERROR_IS_OK(result)) {
8246 result = mod_a_printer(printer, 2);
8249 done:
8250 free_a_printer(&printer, 2);
8252 return result;
8255 /****************************************************************
8256 _spoolss_ResetPrinter
8257 ****************************************************************/
8259 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8260 struct spoolss_ResetPrinter *r)
8262 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8263 int snum;
8265 DEBUG(5,("_spoolss_ResetPrinter\n"));
8268 * All we do is to check to see if the handle and queue is valid.
8269 * This call really doesn't mean anything to us because we only
8270 * support RAW printing. --jerry
8273 if (!Printer) {
8274 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8275 OUR_HANDLE(r->in.handle)));
8276 return WERR_BADFID;
8279 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8280 return WERR_BADFID;
8283 /* blindly return success */
8284 return WERR_OK;
8287 /****************************************************************
8288 _spoolss_DeletePrinterData
8289 ****************************************************************/
8291 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8292 struct spoolss_DeletePrinterData *r)
8294 NT_PRINTER_INFO_LEVEL *printer = NULL;
8295 int snum=0;
8296 WERROR status = WERR_OK;
8297 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8299 DEBUG(5,("_spoolss_DeletePrinterData\n"));
8301 if (!Printer) {
8302 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8303 OUR_HANDLE(r->in.handle)));
8304 return WERR_BADFID;
8307 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8308 return WERR_BADFID;
8310 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8311 DEBUG(3, ("_spoolss_DeletePrinterData: "
8312 "printer properties change denied by handle\n"));
8313 return WERR_ACCESS_DENIED;
8316 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8317 if (!W_ERROR_IS_OK(status))
8318 return status;
8320 if (!r->in.value_name) {
8321 free_a_printer(&printer, 2);
8322 return WERR_NOMEM;
8325 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8326 r->in.value_name );
8328 if ( W_ERROR_IS_OK(status) )
8329 mod_a_printer( printer, 2 );
8331 free_a_printer(&printer, 2);
8333 return status;
8336 /****************************************************************
8337 _spoolss_AddForm
8338 ****************************************************************/
8340 WERROR _spoolss_AddForm(pipes_struct *p,
8341 struct spoolss_AddForm *r)
8343 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8344 nt_forms_struct tmpForm;
8345 int snum = -1;
8346 WERROR status = WERR_OK;
8347 NT_PRINTER_INFO_LEVEL *printer = NULL;
8348 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8350 int count=0;
8351 nt_forms_struct *list=NULL;
8352 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8354 DEBUG(5,("_spoolss_AddForm\n"));
8356 if (!Printer) {
8357 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8358 OUR_HANDLE(r->in.handle)));
8359 return WERR_BADFID;
8363 /* forms can be added on printer of on the print server handle */
8365 if ( Printer->printer_type == SPLHND_PRINTER )
8367 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8368 return WERR_BADFID;
8370 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8371 if (!W_ERROR_IS_OK(status))
8372 goto done;
8375 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8376 and not a printer admin, then fail */
8378 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8379 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8380 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8381 NULL, NULL,
8382 p->server_info->ptok,
8383 lp_printer_admin(snum))) {
8384 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8385 return WERR_ACCESS_DENIED;
8388 /* can't add if builtin */
8390 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8391 status = WERR_FILE_EXISTS;
8392 goto done;
8395 count = get_ntforms(&list);
8397 if(!add_a_form(&list, form, &count)) {
8398 status = WERR_NOMEM;
8399 goto done;
8402 become_root();
8403 write_ntforms(&list, count);
8404 unbecome_root();
8407 * ChangeID must always be set if this is a printer
8410 if ( Printer->printer_type == SPLHND_PRINTER )
8411 status = mod_a_printer(printer, 2);
8413 done:
8414 if ( printer )
8415 free_a_printer(&printer, 2);
8416 SAFE_FREE(list);
8418 return status;
8421 /****************************************************************
8422 _spoolss_DeleteForm
8423 ****************************************************************/
8425 WERROR _spoolss_DeleteForm(pipes_struct *p,
8426 struct spoolss_DeleteForm *r)
8428 const char *form_name = r->in.form_name;
8429 nt_forms_struct tmpForm;
8430 int count=0;
8431 nt_forms_struct *list=NULL;
8432 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8433 int snum = -1;
8434 WERROR status = WERR_OK;
8435 NT_PRINTER_INFO_LEVEL *printer = NULL;
8436 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8437 bool ret = false;
8439 DEBUG(5,("_spoolss_DeleteForm\n"));
8441 if (!Printer) {
8442 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8443 OUR_HANDLE(r->in.handle)));
8444 return WERR_BADFID;
8447 /* forms can be deleted on printer of on the print server handle */
8449 if ( Printer->printer_type == SPLHND_PRINTER )
8451 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8452 return WERR_BADFID;
8454 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8455 if (!W_ERROR_IS_OK(status))
8456 goto done;
8459 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8460 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8461 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8462 NULL, NULL,
8463 p->server_info->ptok,
8464 lp_printer_admin(snum))) {
8465 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8466 return WERR_ACCESS_DENIED;
8470 /* can't delete if builtin */
8472 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8473 status = WERR_INVALID_PARAM;
8474 goto done;
8477 count = get_ntforms(&list);
8479 become_root();
8480 ret = delete_a_form(&list, form_name, &count, &status);
8481 unbecome_root();
8482 if (ret == false) {
8483 goto done;
8487 * ChangeID must always be set if this is a printer
8490 if ( Printer->printer_type == SPLHND_PRINTER )
8491 status = mod_a_printer(printer, 2);
8493 done:
8494 if ( printer )
8495 free_a_printer(&printer, 2);
8496 SAFE_FREE(list);
8498 return status;
8501 /****************************************************************
8502 _spoolss_SetForm
8503 ****************************************************************/
8505 WERROR _spoolss_SetForm(pipes_struct *p,
8506 struct spoolss_SetForm *r)
8508 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8509 nt_forms_struct tmpForm;
8510 int snum = -1;
8511 WERROR status = WERR_OK;
8512 NT_PRINTER_INFO_LEVEL *printer = NULL;
8513 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8515 int count=0;
8516 nt_forms_struct *list=NULL;
8517 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8519 DEBUG(5,("_spoolss_SetForm\n"));
8521 if (!Printer) {
8522 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8523 OUR_HANDLE(r->in.handle)));
8524 return WERR_BADFID;
8527 /* forms can be modified on printer of on the print server handle */
8529 if ( Printer->printer_type == SPLHND_PRINTER )
8531 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8532 return WERR_BADFID;
8534 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8535 if (!W_ERROR_IS_OK(status))
8536 goto done;
8539 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8540 and not a printer admin, then fail */
8542 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8543 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8544 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8545 NULL, NULL,
8546 p->server_info->ptok,
8547 lp_printer_admin(snum))) {
8548 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8549 return WERR_ACCESS_DENIED;
8552 /* can't set if builtin */
8553 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8554 status = WERR_INVALID_PARAM;
8555 goto done;
8558 count = get_ntforms(&list);
8559 update_a_form(&list, form, count);
8560 become_root();
8561 write_ntforms(&list, count);
8562 unbecome_root();
8565 * ChangeID must always be set if this is a printer
8568 if ( Printer->printer_type == SPLHND_PRINTER )
8569 status = mod_a_printer(printer, 2);
8572 done:
8573 if ( printer )
8574 free_a_printer(&printer, 2);
8575 SAFE_FREE(list);
8577 return status;
8580 /****************************************************************************
8581 fill_print_processor1
8582 ****************************************************************************/
8584 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8585 struct spoolss_PrintProcessorInfo1 *r,
8586 const char *print_processor_name)
8588 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8589 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8591 return WERR_OK;
8594 /****************************************************************************
8595 enumprintprocessors level 1.
8596 ****************************************************************************/
8598 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8599 union spoolss_PrintProcessorInfo **info_p,
8600 uint32_t *count)
8602 union spoolss_PrintProcessorInfo *info;
8603 WERROR result;
8605 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8606 W_ERROR_HAVE_NO_MEMORY(info);
8608 *count = 1;
8610 result = fill_print_processor1(info, &info[0].info1, "winprint");
8611 if (!W_ERROR_IS_OK(result)) {
8612 goto out;
8615 out:
8616 if (!W_ERROR_IS_OK(result)) {
8617 TALLOC_FREE(info);
8618 *count = 0;
8619 return result;
8622 *info_p = info;
8624 return WERR_OK;
8627 /****************************************************************
8628 _spoolss_EnumPrintProcessors
8629 ****************************************************************/
8631 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8632 struct spoolss_EnumPrintProcessors *r)
8634 WERROR result;
8636 /* that's an [in out] buffer */
8638 if (!r->in.buffer && (r->in.offered != 0)) {
8639 return WERR_INVALID_PARAM;
8642 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8645 * Enumerate the print processors ...
8647 * Just reply with "winprint", to keep NT happy
8648 * and I can use my nice printer checker.
8651 *r->out.count = 0;
8652 *r->out.needed = 0;
8653 *r->out.info = NULL;
8655 switch (r->in.level) {
8656 case 1:
8657 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8658 r->out.count);
8659 break;
8660 default:
8661 return WERR_UNKNOWN_LEVEL;
8664 if (!W_ERROR_IS_OK(result)) {
8665 return result;
8668 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8669 spoolss_EnumPrintProcessors, NULL,
8670 *r->out.info, r->in.level,
8671 *r->out.count);
8672 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8673 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8675 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8678 /****************************************************************************
8679 fill_printprocdatatype1
8680 ****************************************************************************/
8682 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8683 struct spoolss_PrintProcDataTypesInfo1 *r,
8684 const char *name_array)
8686 r->name_array = talloc_strdup(mem_ctx, name_array);
8687 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8689 return WERR_OK;
8692 /****************************************************************************
8693 enumprintprocdatatypes level 1.
8694 ****************************************************************************/
8696 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8697 union spoolss_PrintProcDataTypesInfo **info_p,
8698 uint32_t *count)
8700 WERROR result;
8701 union spoolss_PrintProcDataTypesInfo *info;
8703 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8704 W_ERROR_HAVE_NO_MEMORY(info);
8706 *count = 1;
8708 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8709 if (!W_ERROR_IS_OK(result)) {
8710 goto out;
8713 out:
8714 if (!W_ERROR_IS_OK(result)) {
8715 TALLOC_FREE(info);
8716 *count = 0;
8717 return result;
8720 *info_p = info;
8722 return WERR_OK;
8725 /****************************************************************
8726 _spoolss_EnumPrintProcDataTypes
8727 ****************************************************************/
8729 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8730 struct spoolss_EnumPrintProcDataTypes *r)
8732 WERROR result;
8734 /* that's an [in out] buffer */
8736 if (!r->in.buffer && (r->in.offered != 0)) {
8737 return WERR_INVALID_PARAM;
8740 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8742 *r->out.count = 0;
8743 *r->out.needed = 0;
8744 *r->out.info = NULL;
8746 switch (r->in.level) {
8747 case 1:
8748 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8749 r->out.count);
8750 break;
8751 default:
8752 return WERR_UNKNOWN_LEVEL;
8755 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8756 spoolss_EnumPrintProcDataTypes, NULL,
8757 *r->out.info, r->in.level,
8758 *r->out.count);
8759 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8760 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8762 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8765 /****************************************************************************
8766 fill_monitor_1
8767 ****************************************************************************/
8769 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8770 struct spoolss_MonitorInfo1 *r,
8771 const char *monitor_name)
8773 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8774 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8776 return WERR_OK;
8779 /****************************************************************************
8780 fill_monitor_2
8781 ****************************************************************************/
8783 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8784 struct spoolss_MonitorInfo2 *r,
8785 const char *monitor_name,
8786 const char *environment,
8787 const char *dll_name)
8789 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8790 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8791 r->environment = talloc_strdup(mem_ctx, environment);
8792 W_ERROR_HAVE_NO_MEMORY(r->environment);
8793 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8794 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8796 return WERR_OK;
8799 /****************************************************************************
8800 enumprintmonitors level 1.
8801 ****************************************************************************/
8803 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8804 union spoolss_MonitorInfo **info_p,
8805 uint32_t *count)
8807 union spoolss_MonitorInfo *info;
8808 WERROR result = WERR_OK;
8810 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8811 W_ERROR_HAVE_NO_MEMORY(info);
8813 *count = 2;
8815 result = fill_monitor_1(info, &info[0].info1,
8816 SPL_LOCAL_PORT);
8817 if (!W_ERROR_IS_OK(result)) {
8818 goto out;
8821 result = fill_monitor_1(info, &info[1].info1,
8822 SPL_TCPIP_PORT);
8823 if (!W_ERROR_IS_OK(result)) {
8824 goto out;
8827 out:
8828 if (!W_ERROR_IS_OK(result)) {
8829 TALLOC_FREE(info);
8830 *count = 0;
8831 return result;
8834 *info_p = info;
8836 return WERR_OK;
8839 /****************************************************************************
8840 enumprintmonitors level 2.
8841 ****************************************************************************/
8843 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8844 union spoolss_MonitorInfo **info_p,
8845 uint32_t *count)
8847 union spoolss_MonitorInfo *info;
8848 WERROR result = WERR_OK;
8850 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8851 W_ERROR_HAVE_NO_MEMORY(info);
8853 *count = 2;
8855 result = fill_monitor_2(info, &info[0].info2,
8856 SPL_LOCAL_PORT,
8857 "Windows NT X86", /* FIXME */
8858 "localmon.dll");
8859 if (!W_ERROR_IS_OK(result)) {
8860 goto out;
8863 result = fill_monitor_2(info, &info[1].info2,
8864 SPL_TCPIP_PORT,
8865 "Windows NT X86", /* FIXME */
8866 "tcpmon.dll");
8867 if (!W_ERROR_IS_OK(result)) {
8868 goto out;
8871 out:
8872 if (!W_ERROR_IS_OK(result)) {
8873 TALLOC_FREE(info);
8874 *count = 0;
8875 return result;
8878 *info_p = info;
8880 return WERR_OK;
8883 /****************************************************************
8884 _spoolss_EnumMonitors
8885 ****************************************************************/
8887 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8888 struct spoolss_EnumMonitors *r)
8890 WERROR result;
8892 /* that's an [in out] buffer */
8894 if (!r->in.buffer && (r->in.offered != 0)) {
8895 return WERR_INVALID_PARAM;
8898 DEBUG(5,("_spoolss_EnumMonitors\n"));
8901 * Enumerate the print monitors ...
8903 * Just reply with "Local Port", to keep NT happy
8904 * and I can use my nice printer checker.
8907 *r->out.count = 0;
8908 *r->out.needed = 0;
8909 *r->out.info = NULL;
8911 switch (r->in.level) {
8912 case 1:
8913 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8914 r->out.count);
8915 break;
8916 case 2:
8917 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8918 r->out.count);
8919 break;
8920 default:
8921 return WERR_UNKNOWN_LEVEL;
8924 if (!W_ERROR_IS_OK(result)) {
8925 return result;
8928 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8929 spoolss_EnumMonitors, NULL,
8930 *r->out.info, r->in.level,
8931 *r->out.count);
8932 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8933 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8935 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8938 /****************************************************************************
8939 ****************************************************************************/
8941 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8942 const print_queue_struct *queue,
8943 int count, int snum,
8944 const NT_PRINTER_INFO_LEVEL *ntprinter,
8945 uint32_t jobid,
8946 struct spoolss_JobInfo1 *r)
8948 int i = 0;
8949 bool found = false;
8951 for (i=0; i<count && found == false; i++) {
8952 if (queue[i].job == (int)jobid) {
8953 found = true;
8957 if (found == false) {
8958 /* NT treats not found as bad param... yet another bad choice */
8959 return WERR_INVALID_PARAM;
8962 return fill_job_info1(mem_ctx,
8964 &queue[i-1],
8966 snum,
8967 ntprinter);
8970 /****************************************************************************
8971 ****************************************************************************/
8973 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8974 const print_queue_struct *queue,
8975 int count, int snum,
8976 const NT_PRINTER_INFO_LEVEL *ntprinter,
8977 uint32_t jobid,
8978 struct spoolss_JobInfo2 *r)
8980 int i = 0;
8981 bool found = false;
8982 struct spoolss_DeviceMode *devmode;
8983 NT_DEVICEMODE *nt_devmode;
8984 WERROR result;
8986 for (i=0; i<count && found == false; i++) {
8987 if (queue[i].job == (int)jobid) {
8988 found = true;
8992 if (found == false) {
8993 /* NT treats not found as bad param... yet another bad
8994 choice */
8995 return WERR_INVALID_PARAM;
8999 * if the print job does not have a DEVMODE associated with it,
9000 * just use the one for the printer. A NULL devicemode is not
9001 * a failure condition
9004 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9005 if (nt_devmode) {
9006 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
9007 W_ERROR_HAVE_NO_MEMORY(devmode);
9008 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
9009 if (!W_ERROR_IS_OK(result)) {
9010 return result;
9012 } else {
9013 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
9014 W_ERROR_HAVE_NO_MEMORY(devmode);
9017 return fill_job_info2(mem_ctx,
9019 &queue[i-1],
9021 snum,
9022 ntprinter,
9023 devmode);
9026 /****************************************************************
9027 _spoolss_GetJob
9028 ****************************************************************/
9030 WERROR _spoolss_GetJob(pipes_struct *p,
9031 struct spoolss_GetJob *r)
9033 WERROR result = WERR_OK;
9034 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9035 int snum;
9036 int count;
9037 print_queue_struct *queue = NULL;
9038 print_status_struct prt_status;
9040 /* that's an [in out] buffer */
9042 if (!r->in.buffer && (r->in.offered != 0)) {
9043 return WERR_INVALID_PARAM;
9046 DEBUG(5,("_spoolss_GetJob\n"));
9048 *r->out.needed = 0;
9050 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9051 return WERR_BADFID;
9054 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9055 if (!W_ERROR_IS_OK(result)) {
9056 return result;
9059 count = print_queue_status(snum, &queue, &prt_status);
9061 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9062 count, prt_status.status, prt_status.message));
9064 switch (r->in.level) {
9065 case 1:
9066 result = getjob_level_1(p->mem_ctx,
9067 queue, count, snum, ntprinter,
9068 r->in.job_id, &r->out.info->info1);
9069 break;
9070 case 2:
9071 result = getjob_level_2(p->mem_ctx,
9072 queue, count, snum, ntprinter,
9073 r->in.job_id, &r->out.info->info2);
9074 break;
9075 default:
9076 result = WERR_UNKNOWN_LEVEL;
9077 break;
9080 SAFE_FREE(queue);
9081 free_a_printer(&ntprinter, 2);
9083 if (!W_ERROR_IS_OK(result)) {
9084 TALLOC_FREE(r->out.info);
9085 return result;
9088 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9089 r->out.info, r->in.level);
9090 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9092 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9095 /****************************************************************
9096 _spoolss_GetPrinterDataEx
9098 From MSDN documentation of GetPrinterDataEx: pass request
9099 to GetPrinterData if key is "PrinterDriverData".
9100 ****************************************************************/
9102 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9103 struct spoolss_GetPrinterDataEx *r)
9106 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9107 struct regval_blob *val = NULL;
9108 NT_PRINTER_INFO_LEVEL *printer = NULL;
9109 int snum = 0;
9110 WERROR result = WERR_OK;
9112 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9114 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9115 r->in.key_name, r->in.value_name));
9117 /* in case of problem, return some default values */
9119 *r->out.needed = 0;
9120 *r->out.type = REG_NONE;
9122 if (!Printer) {
9123 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9124 OUR_HANDLE(r->in.handle)));
9125 result = WERR_BADFID;
9126 goto done;
9129 /* Is the handle to a printer or to the server? */
9131 if (Printer->printer_type == SPLHND_SERVER) {
9132 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9133 "Not implemented for server handles yet\n"));
9134 result = WERR_INVALID_PARAM;
9135 goto done;
9138 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9139 return WERR_BADFID;
9142 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9143 if (!W_ERROR_IS_OK(result)) {
9144 goto done;
9147 /* check to see if the keyname is valid */
9148 if (!strlen(r->in.key_name)) {
9149 result = WERR_INVALID_PARAM;
9150 goto done;
9153 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9154 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9155 "Invalid keyname [%s]\n", r->in.key_name ));
9156 result = WERR_BADFILE;
9157 goto done;
9160 /* When given a new keyname, we should just create it */
9162 val = get_printer_data(printer->info_2,
9163 r->in.key_name, r->in.value_name);
9164 if (!val) {
9165 result = WERR_BADFILE;
9166 goto done;
9169 *r->out.needed = regval_size(val);
9171 if (*r->out.needed > r->in.offered) {
9172 result = WERR_MORE_DATA;
9173 goto done;
9176 *r->out.type = regval_type(val);
9178 memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
9180 done:
9181 if (printer) {
9182 free_a_printer(&printer, 2);
9185 return result;
9188 /****************************************************************
9189 _spoolss_SetPrinterDataEx
9190 ****************************************************************/
9192 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9193 struct spoolss_SetPrinterDataEx *r)
9195 NT_PRINTER_INFO_LEVEL *printer = NULL;
9196 int snum = 0;
9197 WERROR result = WERR_OK;
9198 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9199 char *oid_string;
9201 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9203 /* From MSDN documentation of SetPrinterDataEx: pass request to
9204 SetPrinterData if key is "PrinterDriverData" */
9206 if (!Printer) {
9207 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9208 OUR_HANDLE(r->in.handle)));
9209 return WERR_BADFID;
9212 if (Printer->printer_type == SPLHND_SERVER) {
9213 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9214 "Not implemented for server handles yet\n"));
9215 return WERR_INVALID_PARAM;
9218 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9219 return WERR_BADFID;
9223 * Access check : NT returns "access denied" if you make a
9224 * SetPrinterData call without the necessary privildge.
9225 * we were originally returning OK if nothing changed
9226 * which made Win2k issue **a lot** of SetPrinterData
9227 * when connecting to a printer --jerry
9230 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9231 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9232 "change denied by handle access permissions\n"));
9233 return WERR_ACCESS_DENIED;
9236 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9237 if (!W_ERROR_IS_OK(result)) {
9238 return result;
9241 /* check for OID in valuename */
9243 oid_string = strchr(r->in.value_name, ',');
9244 if (oid_string) {
9245 *oid_string = '\0';
9246 oid_string++;
9249 /* save the registry data */
9251 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9252 r->in.type, r->in.buffer, r->in.offered);
9254 if (W_ERROR_IS_OK(result)) {
9255 /* save the OID if one was specified */
9256 if (oid_string) {
9257 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9258 r->in.key_name, SPOOL_OID_KEY);
9259 if (!str) {
9260 result = WERR_NOMEM;
9261 goto done;
9265 * I'm not checking the status here on purpose. Don't know
9266 * if this is right, but I'm returning the status from the
9267 * previous set_printer_dataex() call. I have no idea if
9268 * this is right. --jerry
9271 set_printer_dataex(printer, str, r->in.value_name,
9272 REG_SZ, (uint8_t *)oid_string,
9273 strlen(oid_string)+1);
9276 result = mod_a_printer(printer, 2);
9279 done:
9280 free_a_printer(&printer, 2);
9282 return result;
9285 /****************************************************************
9286 _spoolss_DeletePrinterDataEx
9287 ****************************************************************/
9289 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9290 struct spoolss_DeletePrinterDataEx *r)
9292 NT_PRINTER_INFO_LEVEL *printer = NULL;
9293 int snum=0;
9294 WERROR status = WERR_OK;
9295 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9297 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9299 if (!Printer) {
9300 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9301 "Invalid handle (%s:%u:%u).\n",
9302 OUR_HANDLE(r->in.handle)));
9303 return WERR_BADFID;
9306 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9307 return WERR_BADFID;
9309 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9310 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9311 "printer properties change denied by handle\n"));
9312 return WERR_ACCESS_DENIED;
9315 if (!r->in.value_name || !r->in.key_name) {
9316 return WERR_NOMEM;
9319 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9320 if (!W_ERROR_IS_OK(status))
9321 return status;
9323 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9325 if ( W_ERROR_IS_OK(status) )
9326 mod_a_printer( printer, 2 );
9328 free_a_printer(&printer, 2);
9330 return status;
9333 /****************************************************************
9334 _spoolss_EnumPrinterKey
9335 ****************************************************************/
9337 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9338 struct spoolss_EnumPrinterKey *r)
9340 fstring *keynames = NULL;
9341 int num_keys;
9342 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9343 NT_PRINTER_DATA *data;
9344 NT_PRINTER_INFO_LEVEL *printer = NULL;
9345 int snum = 0;
9346 WERROR result = WERR_BADFILE;
9347 int i;
9348 const char **array = NULL;
9351 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9353 if (!Printer) {
9354 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9355 OUR_HANDLE(r->in.handle)));
9356 return WERR_BADFID;
9359 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9360 return WERR_BADFID;
9363 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9364 if (!W_ERROR_IS_OK(result)) {
9365 return result;
9368 /* get the list of subkey names */
9370 data = printer->info_2->data;
9372 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9373 if (num_keys == -1) {
9374 result = WERR_BADFILE;
9375 goto done;
9378 *r->out.needed = 4;
9380 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9381 if (!array) {
9382 result = WERR_NOMEM;
9383 goto done;
9386 for (i=0; i < num_keys; i++) {
9387 array[i] = talloc_strdup(array, keynames[i]);
9388 if (!array[i]) {
9389 result = WERR_NOMEM;
9390 goto done;
9393 *r->out.needed += strlen_m_term(keynames[i]) * 2;
9396 if (r->in.offered < *r->out.needed) {
9397 result = WERR_MORE_DATA;
9398 goto done;
9401 result = WERR_OK;
9403 *r->out.key_buffer = array;
9405 done:
9406 if (!W_ERROR_IS_OK(result)) {
9407 TALLOC_FREE(array);
9408 ZERO_STRUCTP(r->out.key_buffer);
9411 free_a_printer(&printer, 2);
9412 SAFE_FREE(keynames);
9414 return result;
9417 /****************************************************************
9418 _spoolss_DeletePrinterKey
9419 ****************************************************************/
9421 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9422 struct spoolss_DeletePrinterKey *r)
9424 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9425 NT_PRINTER_INFO_LEVEL *printer = NULL;
9426 int snum=0;
9427 WERROR status;
9429 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9431 if (!Printer) {
9432 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9433 OUR_HANDLE(r->in.handle)));
9434 return WERR_BADFID;
9437 /* if keyname == NULL, return error */
9439 if ( !r->in.key_name )
9440 return WERR_INVALID_PARAM;
9442 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9443 return WERR_BADFID;
9445 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9446 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9447 "printer properties change denied by handle\n"));
9448 return WERR_ACCESS_DENIED;
9451 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9452 if (!W_ERROR_IS_OK(status))
9453 return status;
9455 /* delete the key and all subneys */
9457 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9459 if ( W_ERROR_IS_OK(status) )
9460 status = mod_a_printer(printer, 2);
9462 free_a_printer( &printer, 2 );
9464 return status;
9467 /****************************************************************
9468 ****************************************************************/
9470 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9471 struct regval_blob *v,
9472 struct spoolss_PrinterEnumValues *r)
9474 WERROR result;
9476 r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9477 W_ERROR_HAVE_NO_MEMORY(r->data);
9479 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
9480 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9482 r->type = regval_type(v);
9483 r->data_length = regval_size(v);
9485 if (r->data_length) {
9486 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9487 regval_size(v));
9488 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9489 r->data,
9490 r->type);
9491 if (!W_ERROR_IS_OK(result)) {
9492 return result;
9496 return WERR_OK;
9499 /****************************************************************
9500 _spoolss_EnumPrinterDataEx
9501 ****************************************************************/
9503 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9504 struct spoolss_EnumPrinterDataEx *r)
9506 uint32_t count = 0;
9507 NT_PRINTER_INFO_LEVEL *printer = NULL;
9508 struct spoolss_PrinterEnumValues *info = NULL;
9509 NT_PRINTER_DATA *p_data;
9510 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9511 int snum;
9512 WERROR result;
9513 int key_index;
9514 int i;
9516 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9518 *r->out.count = 0;
9519 *r->out.needed = 0;
9520 *r->out.info = NULL;
9522 if (!Printer) {
9523 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9524 OUR_HANDLE(r->in.handle)));
9525 return WERR_BADFID;
9529 * first check for a keyname of NULL or "". Win2k seems to send
9530 * this a lot and we should send back WERR_INVALID_PARAM
9531 * no need to spend time looking up the printer in this case.
9532 * --jerry
9535 if (!strlen(r->in.key_name)) {
9536 result = WERR_INVALID_PARAM;
9537 goto done;
9540 /* get the printer off of disk */
9542 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9543 return WERR_BADFID;
9546 ZERO_STRUCT(printer);
9547 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9548 if (!W_ERROR_IS_OK(result)) {
9549 return result;
9552 /* now look for a match on the key name */
9554 p_data = printer->info_2->data;
9556 key_index = lookup_printerkey(p_data, r->in.key_name);
9557 if (key_index == -1) {
9558 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9559 r->in.key_name));
9560 result = WERR_INVALID_PARAM;
9561 goto done;
9564 /* allocate the memory for the array of pointers -- if necessary */
9566 count = regval_ctr_numvals(p_data->keys[key_index].values);
9567 if (!count) {
9568 result = WERR_OK; /* ??? */
9569 goto done;
9572 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9573 struct spoolss_PrinterEnumValues,
9574 count);
9575 if (!info) {
9576 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9577 result = WERR_NOMEM;
9578 goto done;
9582 * loop through all params and build the array to pass
9583 * back to the client
9586 for (i=0; i < count; i++) {
9588 struct regval_blob *val;
9590 /* lookup the registry value */
9592 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9594 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9596 /* copy the data */
9598 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9599 if (!W_ERROR_IS_OK(result)) {
9600 goto done;
9604 #if 0 /* FIXME - gd */
9605 /* housekeeping information in the reply */
9607 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9608 * the hand marshalled container size is a multiple
9609 * of 4 bytes for RPC alignment.
9612 if (needed % 4) {
9613 needed += 4-(needed % 4);
9615 #endif
9616 *r->out.count = count;
9617 *r->out.info = info;
9619 done:
9621 if (printer) {
9622 free_a_printer(&printer, 2);
9625 if (!W_ERROR_IS_OK(result)) {
9626 return result;
9629 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9630 spoolss_EnumPrinterDataEx, NULL,
9631 *r->out.info,
9632 *r->out.count);
9633 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9634 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9636 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9639 /****************************************************************************
9640 ****************************************************************************/
9642 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9643 const char *servername,
9644 const char *environment,
9645 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9647 WERROR werr;
9648 char *path = NULL;
9650 werr = compose_spoolss_server_path(mem_ctx,
9651 servername,
9652 environment,
9653 SPOOLSS_PRTPROCS_PATH,
9654 &path);
9655 if (!W_ERROR_IS_OK(werr)) {
9656 return werr;
9659 DEBUG(4,("print processor directory: [%s]\n", path));
9661 r->directory_name = path;
9663 return WERR_OK;
9666 /****************************************************************
9667 _spoolss_GetPrintProcessorDirectory
9668 ****************************************************************/
9670 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9671 struct spoolss_GetPrintProcessorDirectory *r)
9673 WERROR result;
9675 /* that's an [in out] buffer */
9677 if (!r->in.buffer && (r->in.offered != 0)) {
9678 return WERR_INVALID_PARAM;
9681 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9682 r->in.level));
9684 *r->out.needed = 0;
9686 /* r->in.level is ignored */
9688 /* We always should reply with a local print processor directory so that
9689 * users are not forced to have a [prnproc$] share on the Samba spoolss
9690 * server - Guenther */
9692 result = getprintprocessordirectory_level_1(p->mem_ctx,
9693 NULL, /* r->in.server */
9694 r->in.environment,
9695 &r->out.info->info1);
9696 if (!W_ERROR_IS_OK(result)) {
9697 TALLOC_FREE(r->out.info);
9698 return result;
9701 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9702 r->out.info, r->in.level);
9703 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9705 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9708 /*******************************************************************
9709 ********************************************************************/
9711 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9712 const char *dllname)
9714 enum ndr_err_code ndr_err;
9715 struct spoolss_MonitorUi ui;
9717 ui.dll_name = dllname;
9719 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9720 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9721 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9722 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9724 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9727 /*******************************************************************
9728 Streams the monitor UI DLL name in UNICODE
9729 *******************************************************************/
9731 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9732 NT_USER_TOKEN *token, DATA_BLOB *in,
9733 DATA_BLOB *out, uint32_t *needed)
9735 const char *dllname = "tcpmonui.dll";
9737 *needed = (strlen(dllname)+1) * 2;
9739 if (out->length < *needed) {
9740 return WERR_INSUFFICIENT_BUFFER;
9743 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9744 return WERR_NOMEM;
9747 return WERR_OK;
9750 /*******************************************************************
9751 ********************************************************************/
9753 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9754 struct spoolss_PortData1 *port1,
9755 const DATA_BLOB *buf)
9757 enum ndr_err_code ndr_err;
9758 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9759 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9760 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9761 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9763 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9766 /*******************************************************************
9767 ********************************************************************/
9769 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9770 struct spoolss_PortData2 *port2,
9771 const DATA_BLOB *buf)
9773 enum ndr_err_code ndr_err;
9774 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9775 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9776 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9777 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9779 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9782 /*******************************************************************
9783 Create a new TCP/IP port
9784 *******************************************************************/
9786 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9787 NT_USER_TOKEN *token, DATA_BLOB *in,
9788 DATA_BLOB *out, uint32_t *needed)
9790 struct spoolss_PortData1 port1;
9791 struct spoolss_PortData2 port2;
9792 char *device_uri = NULL;
9793 uint32_t version;
9795 const char *portname;
9796 const char *hostaddress;
9797 const char *queue;
9798 uint32_t port_number;
9799 uint32_t protocol;
9801 /* peek for spoolss_PortData version */
9803 if (!in || (in->length < (128 + 4))) {
9804 return WERR_GENERAL_FAILURE;
9807 version = IVAL(in->data, 128);
9809 switch (version) {
9810 case 1:
9811 ZERO_STRUCT(port1);
9813 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9814 return WERR_NOMEM;
9817 portname = port1.portname;
9818 hostaddress = port1.hostaddress;
9819 queue = port1.queue;
9820 protocol = port1.protocol;
9821 port_number = port1.port_number;
9823 break;
9824 case 2:
9825 ZERO_STRUCT(port2);
9827 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9828 return WERR_NOMEM;
9831 portname = port2.portname;
9832 hostaddress = port2.hostaddress;
9833 queue = port2.queue;
9834 protocol = port2.protocol;
9835 port_number = port2.port_number;
9837 break;
9838 default:
9839 DEBUG(1,("xcvtcp_addport: "
9840 "unknown version of port_data: %d\n", version));
9841 return WERR_UNKNOWN_PORT;
9844 /* create the device URI and call the add_port_hook() */
9846 switch (protocol) {
9847 case PROTOCOL_RAWTCP_TYPE:
9848 device_uri = talloc_asprintf(mem_ctx,
9849 "socket://%s:%d/", hostaddress,
9850 port_number);
9851 break;
9853 case PROTOCOL_LPR_TYPE:
9854 device_uri = talloc_asprintf(mem_ctx,
9855 "lpr://%s/%s", hostaddress, queue );
9856 break;
9858 default:
9859 return WERR_UNKNOWN_PORT;
9862 if (!device_uri) {
9863 return WERR_NOMEM;
9866 return add_port_hook(mem_ctx, token, portname, device_uri);
9869 /*******************************************************************
9870 *******************************************************************/
9872 struct xcv_api_table xcvtcp_cmds[] = {
9873 { "MonitorUI", xcvtcp_monitorui },
9874 { "AddPort", xcvtcp_addport},
9875 { NULL, NULL }
9878 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9879 NT_USER_TOKEN *token, const char *command,
9880 DATA_BLOB *inbuf,
9881 DATA_BLOB *outbuf,
9882 uint32_t *needed )
9884 int i;
9886 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9888 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9889 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9890 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9893 return WERR_BADFUNC;
9896 /*******************************************************************
9897 *******************************************************************/
9898 #if 0 /* don't support management using the "Local Port" monitor */
9900 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9901 NT_USER_TOKEN *token, DATA_BLOB *in,
9902 DATA_BLOB *out, uint32_t *needed)
9904 const char *dllname = "localui.dll";
9906 *needed = (strlen(dllname)+1) * 2;
9908 if (out->length < *needed) {
9909 return WERR_INSUFFICIENT_BUFFER;
9912 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9913 return WERR_NOMEM;
9916 return WERR_OK;
9919 /*******************************************************************
9920 *******************************************************************/
9922 struct xcv_api_table xcvlocal_cmds[] = {
9923 { "MonitorUI", xcvlocal_monitorui },
9924 { NULL, NULL }
9926 #else
9927 struct xcv_api_table xcvlocal_cmds[] = {
9928 { NULL, NULL }
9930 #endif
9934 /*******************************************************************
9935 *******************************************************************/
9937 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9938 NT_USER_TOKEN *token, const char *command,
9939 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9940 uint32_t *needed)
9942 int i;
9944 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9946 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9947 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9948 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9950 return WERR_BADFUNC;
9953 /****************************************************************
9954 _spoolss_XcvData
9955 ****************************************************************/
9957 WERROR _spoolss_XcvData(pipes_struct *p,
9958 struct spoolss_XcvData *r)
9960 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9961 DATA_BLOB out_data = data_blob_null;
9962 WERROR werror;
9964 if (!Printer) {
9965 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9966 OUR_HANDLE(r->in.handle)));
9967 return WERR_BADFID;
9970 /* Has to be a handle to the TCP/IP port monitor */
9972 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9973 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9974 return WERR_BADFID;
9977 /* requires administrative access to the server */
9979 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9980 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9981 return WERR_ACCESS_DENIED;
9984 /* Allocate the outgoing buffer */
9986 if (r->in.out_data_size) {
9987 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9988 if (out_data.data == NULL) {
9989 return WERR_NOMEM;
9993 switch ( Printer->printer_type ) {
9994 case SPLHND_PORTMON_TCP:
9995 werror = process_xcvtcp_command(p->mem_ctx,
9996 p->server_info->ptok,
9997 r->in.function_name,
9998 &r->in.in_data, &out_data,
9999 r->out.needed);
10000 break;
10001 case SPLHND_PORTMON_LOCAL:
10002 werror = process_xcvlocal_command(p->mem_ctx,
10003 p->server_info->ptok,
10004 r->in.function_name,
10005 &r->in.in_data, &out_data,
10006 r->out.needed);
10007 break;
10008 default:
10009 werror = WERR_INVALID_PRINT_MONITOR;
10012 if (!W_ERROR_IS_OK(werror)) {
10013 return werror;
10016 *r->out.status_code = 0;
10018 memcpy(r->out.out_data, out_data.data, out_data.length);
10020 return WERR_OK;
10023 /****************************************************************
10024 _spoolss_AddPrintProcessor
10025 ****************************************************************/
10027 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10028 struct spoolss_AddPrintProcessor *r)
10030 /* for now, just indicate success and ignore the add. We'll
10031 automatically set the winprint processor for printer
10032 entries later. Used to debug the LexMark Optra S 1855 PCL
10033 driver --jerry */
10035 return WERR_OK;
10038 /****************************************************************
10039 _spoolss_AddPort
10040 ****************************************************************/
10042 WERROR _spoolss_AddPort(pipes_struct *p,
10043 struct spoolss_AddPort *r)
10045 /* do what w2k3 does */
10047 return WERR_NOT_SUPPORTED;
10050 /****************************************************************
10051 _spoolss_GetPrinterDriver
10052 ****************************************************************/
10054 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10055 struct spoolss_GetPrinterDriver *r)
10057 p->rng_fault_state = true;
10058 return WERR_NOT_SUPPORTED;
10061 /****************************************************************
10062 _spoolss_ReadPrinter
10063 ****************************************************************/
10065 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10066 struct spoolss_ReadPrinter *r)
10068 p->rng_fault_state = true;
10069 return WERR_NOT_SUPPORTED;
10072 /****************************************************************
10073 _spoolss_WaitForPrinterChange
10074 ****************************************************************/
10076 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10077 struct spoolss_WaitForPrinterChange *r)
10079 p->rng_fault_state = true;
10080 return WERR_NOT_SUPPORTED;
10083 /****************************************************************
10084 _spoolss_ConfigurePort
10085 ****************************************************************/
10087 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10088 struct spoolss_ConfigurePort *r)
10090 p->rng_fault_state = true;
10091 return WERR_NOT_SUPPORTED;
10094 /****************************************************************
10095 _spoolss_DeletePort
10096 ****************************************************************/
10098 WERROR _spoolss_DeletePort(pipes_struct *p,
10099 struct spoolss_DeletePort *r)
10101 p->rng_fault_state = true;
10102 return WERR_NOT_SUPPORTED;
10105 /****************************************************************
10106 _spoolss_CreatePrinterIC
10107 ****************************************************************/
10109 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10110 struct spoolss_CreatePrinterIC *r)
10112 p->rng_fault_state = true;
10113 return WERR_NOT_SUPPORTED;
10116 /****************************************************************
10117 _spoolss_PlayGDIScriptOnPrinterIC
10118 ****************************************************************/
10120 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10121 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10123 p->rng_fault_state = true;
10124 return WERR_NOT_SUPPORTED;
10127 /****************************************************************
10128 _spoolss_DeletePrinterIC
10129 ****************************************************************/
10131 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10132 struct spoolss_DeletePrinterIC *r)
10134 p->rng_fault_state = true;
10135 return WERR_NOT_SUPPORTED;
10138 /****************************************************************
10139 _spoolss_AddPrinterConnection
10140 ****************************************************************/
10142 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10143 struct spoolss_AddPrinterConnection *r)
10145 p->rng_fault_state = true;
10146 return WERR_NOT_SUPPORTED;
10149 /****************************************************************
10150 _spoolss_DeletePrinterConnection
10151 ****************************************************************/
10153 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10154 struct spoolss_DeletePrinterConnection *r)
10156 p->rng_fault_state = true;
10157 return WERR_NOT_SUPPORTED;
10160 /****************************************************************
10161 _spoolss_PrinterMessageBox
10162 ****************************************************************/
10164 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10165 struct spoolss_PrinterMessageBox *r)
10167 p->rng_fault_state = true;
10168 return WERR_NOT_SUPPORTED;
10171 /****************************************************************
10172 _spoolss_AddMonitor
10173 ****************************************************************/
10175 WERROR _spoolss_AddMonitor(pipes_struct *p,
10176 struct spoolss_AddMonitor *r)
10178 p->rng_fault_state = true;
10179 return WERR_NOT_SUPPORTED;
10182 /****************************************************************
10183 _spoolss_DeleteMonitor
10184 ****************************************************************/
10186 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10187 struct spoolss_DeleteMonitor *r)
10189 p->rng_fault_state = true;
10190 return WERR_NOT_SUPPORTED;
10193 /****************************************************************
10194 _spoolss_DeletePrintProcessor
10195 ****************************************************************/
10197 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10198 struct spoolss_DeletePrintProcessor *r)
10200 p->rng_fault_state = true;
10201 return WERR_NOT_SUPPORTED;
10204 /****************************************************************
10205 _spoolss_AddPrintProvidor
10206 ****************************************************************/
10208 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10209 struct spoolss_AddPrintProvidor *r)
10211 p->rng_fault_state = true;
10212 return WERR_NOT_SUPPORTED;
10215 /****************************************************************
10216 _spoolss_DeletePrintProvidor
10217 ****************************************************************/
10219 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10220 struct spoolss_DeletePrintProvidor *r)
10222 p->rng_fault_state = true;
10223 return WERR_NOT_SUPPORTED;
10226 /****************************************************************
10227 _spoolss_FindFirstPrinterChangeNotification
10228 ****************************************************************/
10230 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10231 struct spoolss_FindFirstPrinterChangeNotification *r)
10233 p->rng_fault_state = true;
10234 return WERR_NOT_SUPPORTED;
10237 /****************************************************************
10238 _spoolss_FindNextPrinterChangeNotification
10239 ****************************************************************/
10241 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10242 struct spoolss_FindNextPrinterChangeNotification *r)
10244 p->rng_fault_state = true;
10245 return WERR_NOT_SUPPORTED;
10248 /****************************************************************
10249 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10250 ****************************************************************/
10252 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10253 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10255 p->rng_fault_state = true;
10256 return WERR_NOT_SUPPORTED;
10259 /****************************************************************
10260 _spoolss_ReplyOpenPrinter
10261 ****************************************************************/
10263 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10264 struct spoolss_ReplyOpenPrinter *r)
10266 p->rng_fault_state = true;
10267 return WERR_NOT_SUPPORTED;
10270 /****************************************************************
10271 _spoolss_RouterReplyPrinter
10272 ****************************************************************/
10274 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10275 struct spoolss_RouterReplyPrinter *r)
10277 p->rng_fault_state = true;
10278 return WERR_NOT_SUPPORTED;
10281 /****************************************************************
10282 _spoolss_ReplyClosePrinter
10283 ****************************************************************/
10285 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10286 struct spoolss_ReplyClosePrinter *r)
10288 p->rng_fault_state = true;
10289 return WERR_NOT_SUPPORTED;
10292 /****************************************************************
10293 _spoolss_AddPortEx
10294 ****************************************************************/
10296 WERROR _spoolss_AddPortEx(pipes_struct *p,
10297 struct spoolss_AddPortEx *r)
10299 p->rng_fault_state = true;
10300 return WERR_NOT_SUPPORTED;
10303 /****************************************************************
10304 _spoolss_RouterFindFirstPrinterChangeNotification
10305 ****************************************************************/
10307 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10308 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10310 p->rng_fault_state = true;
10311 return WERR_NOT_SUPPORTED;
10314 /****************************************************************
10315 _spoolss_SpoolerInit
10316 ****************************************************************/
10318 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10319 struct spoolss_SpoolerInit *r)
10321 p->rng_fault_state = true;
10322 return WERR_NOT_SUPPORTED;
10325 /****************************************************************
10326 _spoolss_ResetPrinterEx
10327 ****************************************************************/
10329 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10330 struct spoolss_ResetPrinterEx *r)
10332 p->rng_fault_state = true;
10333 return WERR_NOT_SUPPORTED;
10336 /****************************************************************
10337 _spoolss_RouterReplyPrinterEx
10338 ****************************************************************/
10340 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10341 struct spoolss_RouterReplyPrinterEx *r)
10343 p->rng_fault_state = true;
10344 return WERR_NOT_SUPPORTED;
10347 /****************************************************************
10348 _spoolss_44
10349 ****************************************************************/
10351 WERROR _spoolss_44(pipes_struct *p,
10352 struct spoolss_44 *r)
10354 p->rng_fault_state = true;
10355 return WERR_NOT_SUPPORTED;
10358 /****************************************************************
10359 _spoolss_47
10360 ****************************************************************/
10362 WERROR _spoolss_47(pipes_struct *p,
10363 struct spoolss_47 *r)
10365 p->rng_fault_state = true;
10366 return WERR_NOT_SUPPORTED;
10369 /****************************************************************
10370 _spoolss_4a
10371 ****************************************************************/
10373 WERROR _spoolss_4a(pipes_struct *p,
10374 struct spoolss_4a *r)
10376 p->rng_fault_state = true;
10377 return WERR_NOT_SUPPORTED;
10380 /****************************************************************
10381 _spoolss_4b
10382 ****************************************************************/
10384 WERROR _spoolss_4b(pipes_struct *p,
10385 struct spoolss_4b *r)
10387 p->rng_fault_state = true;
10388 return WERR_NOT_SUPPORTED;
10391 /****************************************************************
10392 _spoolss_4c
10393 ****************************************************************/
10395 WERROR _spoolss_4c(pipes_struct *p,
10396 struct spoolss_4c *r)
10398 p->rng_fault_state = true;
10399 return WERR_NOT_SUPPORTED;
10402 /****************************************************************
10403 _spoolss_53
10404 ****************************************************************/
10406 WERROR _spoolss_53(pipes_struct *p,
10407 struct spoolss_53 *r)
10409 p->rng_fault_state = true;
10410 return WERR_NOT_SUPPORTED;
10413 /****************************************************************
10414 _spoolss_55
10415 ****************************************************************/
10417 WERROR _spoolss_55(pipes_struct *p,
10418 struct spoolss_55 *r)
10420 p->rng_fault_state = true;
10421 return WERR_NOT_SUPPORTED;
10424 /****************************************************************
10425 _spoolss_56
10426 ****************************************************************/
10428 WERROR _spoolss_56(pipes_struct *p,
10429 struct spoolss_56 *r)
10431 p->rng_fault_state = true;
10432 return WERR_NOT_SUPPORTED;
10435 /****************************************************************
10436 _spoolss_57
10437 ****************************************************************/
10439 WERROR _spoolss_57(pipes_struct *p,
10440 struct spoolss_57 *r)
10442 p->rng_fault_state = true;
10443 return WERR_NOT_SUPPORTED;
10446 /****************************************************************
10447 _spoolss_5a
10448 ****************************************************************/
10450 WERROR _spoolss_5a(pipes_struct *p,
10451 struct spoolss_5a *r)
10453 p->rng_fault_state = true;
10454 return WERR_NOT_SUPPORTED;
10457 /****************************************************************
10458 _spoolss_5b
10459 ****************************************************************/
10461 WERROR _spoolss_5b(pipes_struct *p,
10462 struct spoolss_5b *r)
10464 p->rng_fault_state = true;
10465 return WERR_NOT_SUPPORTED;
10468 /****************************************************************
10469 _spoolss_5c
10470 ****************************************************************/
10472 WERROR _spoolss_5c(pipes_struct *p,
10473 struct spoolss_5c *r)
10475 p->rng_fault_state = true;
10476 return WERR_NOT_SUPPORTED;
10479 /****************************************************************
10480 _spoolss_5d
10481 ****************************************************************/
10483 WERROR _spoolss_5d(pipes_struct *p,
10484 struct spoolss_5d *r)
10486 p->rng_fault_state = true;
10487 return WERR_NOT_SUPPORTED;
10490 /****************************************************************
10491 _spoolss_5e
10492 ****************************************************************/
10494 WERROR _spoolss_5e(pipes_struct *p,
10495 struct spoolss_5e *r)
10497 p->rng_fault_state = true;
10498 return WERR_NOT_SUPPORTED;
10501 /****************************************************************
10502 _spoolss_5f
10503 ****************************************************************/
10505 WERROR _spoolss_5f(pipes_struct *p,
10506 struct spoolss_5f *r)
10508 p->rng_fault_state = true;
10509 return WERR_NOT_SUPPORTED;