s3: Rename new parameter "ldap ref follow" to "ldap follow referral".
[Samba/gebeck_regimport.git] / source3 / rpc_server / srv_spoolss_nt.c
blob682a59b5a8e84d22ae06fcf3b73f31c700090b8a
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 const struct print_architecture_table_node archi_table[]= {
2062 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2063 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2064 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2065 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2066 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2067 {"Windows IA64", SPL_ARCH_IA64, 3 },
2068 {"Windows x64", SPL_ARCH_X64, 3 },
2069 {NULL, "", -1 }
2072 static int get_version_id(const char *arch)
2074 int i;
2076 for (i=0; archi_table[i].long_archi != NULL; i++)
2078 if (strcmp(arch, archi_table[i].long_archi) == 0)
2079 return (archi_table[i].version);
2082 return -1;
2085 /****************************************************************
2086 _spoolss_DeletePrinterDriver
2087 ****************************************************************/
2089 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2090 struct spoolss_DeletePrinterDriver *r)
2092 NT_PRINTER_DRIVER_INFO_LEVEL info;
2093 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2094 int version;
2095 WERROR status;
2096 WERROR status_win2k = WERR_ACCESS_DENIED;
2097 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2099 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2100 and not a printer admin, then fail */
2102 if ( (p->server_info->utok.uid != sec_initial_uid())
2103 && !user_has_privileges(p->server_info->ptok, &se_printop )
2104 && !token_contains_name_in_list(
2105 uidtoname(p->server_info->utok.uid), NULL,
2106 NULL, p->server_info->ptok,
2107 lp_printer_admin(-1)) )
2109 return WERR_ACCESS_DENIED;
2112 /* check that we have a valid driver name first */
2114 if ((version = get_version_id(r->in.architecture)) == -1)
2115 return WERR_INVALID_ENVIRONMENT;
2117 ZERO_STRUCT(info);
2118 ZERO_STRUCT(info_win2k);
2120 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2121 r->in.architecture,
2122 version)))
2124 /* try for Win2k driver if "Windows NT x86" */
2126 if ( version == 2 ) {
2127 version = 3;
2128 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2129 r->in.driver,
2130 r->in.architecture,
2131 version))) {
2132 status = WERR_UNKNOWN_PRINTER_DRIVER;
2133 goto done;
2136 /* otherwise it was a failure */
2137 else {
2138 status = WERR_UNKNOWN_PRINTER_DRIVER;
2139 goto done;
2144 if (printer_driver_in_use(info.info_3)) {
2145 status = WERR_PRINTER_DRIVER_IN_USE;
2146 goto done;
2149 if ( version == 2 )
2151 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2152 r->in.driver,
2153 r->in.architecture, 3)))
2155 /* if we get to here, we now have 2 driver info structures to remove */
2156 /* remove the Win2k driver first*/
2158 status_win2k = delete_printer_driver(
2159 p, info_win2k.info_3, 3, false);
2160 free_a_printer_driver( info_win2k, 3 );
2162 /* this should not have failed---if it did, report to client */
2163 if ( !W_ERROR_IS_OK(status_win2k) )
2165 status = status_win2k;
2166 goto done;
2171 status = delete_printer_driver(p, info.info_3, version, false);
2173 /* if at least one of the deletes succeeded return OK */
2175 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2176 status = WERR_OK;
2178 done:
2179 free_a_printer_driver( info, 3 );
2181 return status;
2184 /****************************************************************
2185 _spoolss_DeletePrinterDriverEx
2186 ****************************************************************/
2188 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2189 struct spoolss_DeletePrinterDriverEx *r)
2191 NT_PRINTER_DRIVER_INFO_LEVEL info;
2192 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2193 int version;
2194 bool delete_files;
2195 WERROR status;
2196 WERROR status_win2k = WERR_ACCESS_DENIED;
2197 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2199 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2200 and not a printer admin, then fail */
2202 if ( (p->server_info->utok.uid != sec_initial_uid())
2203 && !user_has_privileges(p->server_info->ptok, &se_printop )
2204 && !token_contains_name_in_list(
2205 uidtoname(p->server_info->utok.uid), NULL, NULL,
2206 p->server_info->ptok, lp_printer_admin(-1)) )
2208 return WERR_ACCESS_DENIED;
2211 /* check that we have a valid driver name first */
2212 if ((version = get_version_id(r->in.architecture)) == -1) {
2213 /* this is what NT returns */
2214 return WERR_INVALID_ENVIRONMENT;
2217 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2218 version = r->in.version;
2220 ZERO_STRUCT(info);
2221 ZERO_STRUCT(info_win2k);
2223 status = get_a_printer_driver(&info, 3, r->in.driver,
2224 r->in.architecture, version);
2226 if ( !W_ERROR_IS_OK(status) )
2229 * if the client asked for a specific version,
2230 * or this is something other than Windows NT x86,
2231 * then we've failed
2234 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2235 goto done;
2237 /* try for Win2k driver if "Windows NT x86" */
2239 version = 3;
2240 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2241 r->in.architecture,
2242 version))) {
2243 status = WERR_UNKNOWN_PRINTER_DRIVER;
2244 goto done;
2248 if ( printer_driver_in_use(info.info_3) ) {
2249 status = WERR_PRINTER_DRIVER_IN_USE;
2250 goto done;
2254 * we have a couple of cases to consider.
2255 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2256 * then the delete should fail if **any** files overlap with
2257 * other drivers
2258 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2259 * non-overlapping files
2260 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2261 * is set, the do not delete any files
2262 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2265 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2267 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2269 if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2270 /* no idea of the correct error here */
2271 status = WERR_ACCESS_DENIED;
2272 goto done;
2276 /* also check for W32X86/3 if necessary; maybe we already have? */
2278 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2279 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2280 r->in.driver,
2281 r->in.architecture, 3)))
2284 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2285 /* no idea of the correct error here */
2286 free_a_printer_driver( info_win2k, 3 );
2287 status = WERR_ACCESS_DENIED;
2288 goto done;
2291 /* if we get to here, we now have 2 driver info structures to remove */
2292 /* remove the Win2k driver first*/
2294 status_win2k = delete_printer_driver(
2295 p, info_win2k.info_3, 3, delete_files);
2296 free_a_printer_driver( info_win2k, 3 );
2298 /* this should not have failed---if it did, report to client */
2300 if ( !W_ERROR_IS_OK(status_win2k) )
2301 goto done;
2305 status = delete_printer_driver(p, info.info_3, version, delete_files);
2307 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2308 status = WERR_OK;
2309 done:
2310 free_a_printer_driver( info, 3 );
2312 return status;
2316 /****************************************************************************
2317 Internal routine for removing printerdata
2318 ***************************************************************************/
2320 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2322 return delete_printer_data( printer->info_2, key, value );
2325 /****************************************************************************
2326 Internal routine for storing printerdata
2327 ***************************************************************************/
2329 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2330 const char *key, const char *value,
2331 uint32_t type, uint8_t *data, int real_len)
2333 /* the registry objects enforce uniqueness based on value name */
2335 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2338 /********************************************************************
2339 GetPrinterData on a printer server Handle.
2340 ********************************************************************/
2342 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2343 const char *value,
2344 enum winreg_Type *type,
2345 union spoolss_PrinterData *data)
2347 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2349 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2350 *type = REG_DWORD;
2351 data->value = 0x00;
2352 return WERR_OK;
2355 if (!StrCaseCmp(value, "BeepEnabled")) {
2356 *type = REG_DWORD;
2357 data->value = 0x00;
2358 return WERR_OK;
2361 if (!StrCaseCmp(value, "EventLog")) {
2362 *type = REG_DWORD;
2363 /* formally was 0x1b */
2364 data->value = 0x00;
2365 return WERR_OK;
2368 if (!StrCaseCmp(value, "NetPopup")) {
2369 *type = REG_DWORD;
2370 data->value = 0x00;
2371 return WERR_OK;
2374 if (!StrCaseCmp(value, "MajorVersion")) {
2375 *type = REG_DWORD;
2377 /* Windows NT 4.0 seems to not allow uploading of drivers
2378 to a server that reports 0x3 as the MajorVersion.
2379 need to investigate more how Win2k gets around this .
2380 -- jerry */
2382 if (RA_WINNT == get_remote_arch()) {
2383 data->value = 0x02;
2384 } else {
2385 data->value = 0x03;
2388 return WERR_OK;
2391 if (!StrCaseCmp(value, "MinorVersion")) {
2392 *type = REG_DWORD;
2393 data->value = 0x00;
2394 return WERR_OK;
2397 /* REG_BINARY
2398 * uint32_t size = 0x114
2399 * uint32_t major = 5
2400 * uint32_t minor = [0|1]
2401 * uint32_t build = [2195|2600]
2402 * extra unicode string = e.g. "Service Pack 3"
2404 if (!StrCaseCmp(value, "OSVersion")) {
2405 DATA_BLOB blob;
2406 enum ndr_err_code ndr_err;
2407 struct spoolss_OSVersion os;
2409 os.major = 5; /* Windows 2000 == 5.0 */
2410 os.minor = 0;
2411 os.build = 2195; /* build */
2412 os.extra_string = ""; /* leave extra string empty */
2414 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2415 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2416 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2417 return WERR_GENERAL_FAILURE;
2420 *type = REG_BINARY;
2421 data->binary = blob;
2423 return WERR_OK;
2427 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2428 *type = REG_SZ;
2430 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2431 W_ERROR_HAVE_NO_MEMORY(data->string);
2433 return WERR_OK;
2436 if (!StrCaseCmp(value, "Architecture")) {
2437 *type = REG_SZ;
2439 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2440 W_ERROR_HAVE_NO_MEMORY(data->string);
2442 return WERR_OK;
2445 if (!StrCaseCmp(value, "DsPresent")) {
2446 *type = REG_DWORD;
2448 /* only show the publish check box if we are a
2449 member of a AD domain */
2451 if (lp_security() == SEC_ADS) {
2452 data->value = 0x01;
2453 } else {
2454 data->value = 0x00;
2456 return WERR_OK;
2459 if (!StrCaseCmp(value, "DNSMachineName")) {
2460 const char *hostname = get_mydnsfullname();
2462 if (!hostname) {
2463 return WERR_BADFILE;
2466 *type = REG_SZ;
2467 data->string = talloc_strdup(mem_ctx, hostname);
2468 W_ERROR_HAVE_NO_MEMORY(data->string);
2470 return WERR_OK;
2473 return WERR_INVALID_PARAM;
2476 /****************************************************************
2477 _spoolss_GetPrinterData
2478 ****************************************************************/
2480 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2481 struct spoolss_GetPrinterData *r)
2483 WERROR result;
2484 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2485 NT_PRINTER_INFO_LEVEL *printer = NULL;
2486 int snum = 0;
2489 * Reminder: when it's a string, the length is in BYTES
2490 * even if UNICODE is negociated.
2492 * JFM, 4/19/1999
2495 /* in case of problem, return some default values */
2497 *r->out.needed = 0;
2498 *r->out.type = 0;
2500 DEBUG(4,("_spoolss_GetPrinterData\n"));
2502 if (!Printer) {
2503 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2504 OUR_HANDLE(r->in.handle)));
2505 result = WERR_BADFID;
2506 goto done;
2509 if (Printer->printer_type == SPLHND_SERVER) {
2510 result = getprinterdata_printer_server(p->mem_ctx,
2511 r->in.value_name,
2512 r->out.type,
2513 r->out.data);
2514 } else {
2515 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2516 result = WERR_BADFID;
2517 goto done;
2520 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2521 if (!W_ERROR_IS_OK(result)) {
2522 goto done;
2525 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2527 if (strequal(r->in.value_name, "ChangeId")) {
2528 *r->out.type = REG_DWORD;
2529 r->out.data->value = printer->info_2->changeid;
2530 result = WERR_OK;
2531 } else {
2532 struct regval_blob *v;
2533 DATA_BLOB blob;
2535 v = get_printer_data(printer->info_2,
2536 SPOOL_PRINTERDATA_KEY,
2537 r->in.value_name);
2538 if (!v) {
2539 result = WERR_BADFILE;
2540 goto done;
2543 *r->out.type = v->type;
2545 blob = data_blob_const(v->data_p, v->size);
2547 result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2548 r->out.data,
2549 *r->out.type);
2553 done:
2554 /* cleanup & exit */
2556 if (printer) {
2557 free_a_printer(&printer, 2);
2560 if (!W_ERROR_IS_OK(result)) {
2561 return result;
2564 *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2565 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2566 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2568 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2571 /*********************************************************
2572 Connect to the client machine.
2573 **********************************************************/
2575 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2576 struct sockaddr_storage *client_ss, const char *remote_machine)
2578 NTSTATUS ret;
2579 struct cli_state *the_cli;
2580 struct sockaddr_storage rm_addr;
2582 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2583 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2584 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2585 return false;
2588 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2589 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2590 return false;
2592 } else {
2593 char addr[INET6_ADDRSTRLEN];
2594 rm_addr = *client_ss;
2595 print_sockaddr(addr, sizeof(addr), &rm_addr);
2596 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2597 addr));
2600 /* setup the connection */
2602 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2603 &rm_addr, 0, "IPC$", "IPC",
2604 "", /* username */
2605 "", /* domain */
2606 "", /* password */
2607 0, lp_client_signing(), NULL );
2609 if ( !NT_STATUS_IS_OK( ret ) ) {
2610 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2611 remote_machine ));
2612 return false;
2615 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2616 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2617 cli_shutdown(the_cli);
2618 return false;
2622 * Ok - we have an anonymous connection to the IPC$ share.
2623 * Now start the NT Domain stuff :-).
2626 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2627 if (!NT_STATUS_IS_OK(ret)) {
2628 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2629 remote_machine, nt_errstr(ret)));
2630 cli_shutdown(the_cli);
2631 return false;
2634 return true;
2637 /***************************************************************************
2638 Connect to the client.
2639 ****************************************************************************/
2641 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2642 uint32_t localprinter, uint32_t type,
2643 struct policy_handle *handle,
2644 struct sockaddr_storage *client_ss)
2646 WERROR result;
2647 NTSTATUS status;
2650 * If it's the first connection, contact the client
2651 * and connect to the IPC$ share anonymously
2653 if (smb_connections==0) {
2654 fstring unix_printer;
2656 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2658 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2659 return false;
2661 messaging_register(smbd_messaging_context(), NULL,
2662 MSG_PRINTER_NOTIFY2,
2663 receive_notify2_message_list);
2664 /* Tell the connections db we're now interested in printer
2665 * notify messages. */
2666 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2670 * Tell the specific printing tdb we want messages for this printer
2671 * by registering our PID.
2674 if (!print_notify_register_pid(snum))
2675 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2677 smb_connections++;
2679 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2680 printer,
2681 localprinter,
2682 type,
2684 NULL,
2685 handle,
2686 &result);
2687 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2688 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2689 win_errstr(result)));
2691 return (W_ERROR_IS_OK(result));
2694 /****************************************************************
2695 ****************************************************************/
2697 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2698 const struct spoolss_NotifyOption *r)
2700 struct spoolss_NotifyOption *option;
2701 uint32_t i,k;
2703 if (!r) {
2704 return NULL;
2707 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2708 if (!option) {
2709 return NULL;
2712 *option = *r;
2714 if (!option->count) {
2715 return option;
2718 option->types = talloc_zero_array(option,
2719 struct spoolss_NotifyOptionType, option->count);
2720 if (!option->types) {
2721 talloc_free(option);
2722 return NULL;
2725 for (i=0; i < option->count; i++) {
2726 option->types[i] = r->types[i];
2728 if (option->types[i].count) {
2729 option->types[i].fields = talloc_zero_array(option,
2730 union spoolss_Field, option->types[i].count);
2731 if (!option->types[i].fields) {
2732 talloc_free(option);
2733 return NULL;
2735 for (k=0; k<option->types[i].count; k++) {
2736 option->types[i].fields[k] =
2737 r->types[i].fields[k];
2742 return option;
2745 /****************************************************************
2746 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2748 * before replying OK: status=0 a rpc call is made to the workstation
2749 * asking ReplyOpenPrinter
2751 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2752 * called from api_spoolss_rffpcnex
2753 ****************************************************************/
2755 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2756 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2758 int snum = -1;
2759 struct spoolss_NotifyOption *option = r->in.notify_options;
2760 struct sockaddr_storage client_ss;
2762 /* store the notify value in the printer struct */
2764 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2766 if (!Printer) {
2767 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2768 "Invalid handle (%s:%u:%u).\n",
2769 OUR_HANDLE(r->in.handle)));
2770 return WERR_BADFID;
2773 Printer->notify.flags = r->in.flags;
2774 Printer->notify.options = r->in.options;
2775 Printer->notify.printerlocal = r->in.printer_local;
2777 TALLOC_FREE(Printer->notify.option);
2778 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2780 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2782 /* Connect to the client machine and send a ReplyOpenPrinter */
2784 if ( Printer->printer_type == SPLHND_SERVER)
2785 snum = -1;
2786 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2787 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2788 return WERR_BADFID;
2790 if (!interpret_string_addr(&client_ss, p->client_address,
2791 AI_NUMERICHOST)) {
2792 return WERR_SERVER_UNAVAILABLE;
2795 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2796 Printer->notify.printerlocal, 1,
2797 &Printer->notify.client_hnd, &client_ss))
2798 return WERR_SERVER_UNAVAILABLE;
2800 Printer->notify.client_connected = true;
2802 return WERR_OK;
2805 /*******************************************************************
2806 * fill a notify_info_data with the servername
2807 ********************************************************************/
2809 void spoolss_notify_server_name(int snum,
2810 struct spoolss_Notify *data,
2811 print_queue_struct *queue,
2812 NT_PRINTER_INFO_LEVEL *printer,
2813 TALLOC_CTX *mem_ctx)
2815 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2818 /*******************************************************************
2819 * fill a notify_info_data with the printername (not including the servername).
2820 ********************************************************************/
2822 void spoolss_notify_printer_name(int snum,
2823 struct spoolss_Notify *data,
2824 print_queue_struct *queue,
2825 NT_PRINTER_INFO_LEVEL *printer,
2826 TALLOC_CTX *mem_ctx)
2828 /* the notify name should not contain the \\server\ part */
2829 char *p = strrchr(printer->info_2->printername, '\\');
2831 if (!p) {
2832 p = printer->info_2->printername;
2833 } else {
2834 p++;
2837 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2840 /*******************************************************************
2841 * fill a notify_info_data with the servicename
2842 ********************************************************************/
2844 void spoolss_notify_share_name(int snum,
2845 struct spoolss_Notify *data,
2846 print_queue_struct *queue,
2847 NT_PRINTER_INFO_LEVEL *printer,
2848 TALLOC_CTX *mem_ctx)
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2853 /*******************************************************************
2854 * fill a notify_info_data with the port name
2855 ********************************************************************/
2857 void spoolss_notify_port_name(int snum,
2858 struct spoolss_Notify *data,
2859 print_queue_struct *queue,
2860 NT_PRINTER_INFO_LEVEL *printer,
2861 TALLOC_CTX *mem_ctx)
2863 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2866 /*******************************************************************
2867 * fill a notify_info_data with the printername
2868 * but it doesn't exist, have to see what to do
2869 ********************************************************************/
2871 void spoolss_notify_driver_name(int snum,
2872 struct spoolss_Notify *data,
2873 print_queue_struct *queue,
2874 NT_PRINTER_INFO_LEVEL *printer,
2875 TALLOC_CTX *mem_ctx)
2877 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2880 /*******************************************************************
2881 * fill a notify_info_data with the comment
2882 ********************************************************************/
2884 void spoolss_notify_comment(int snum,
2885 struct spoolss_Notify *data,
2886 print_queue_struct *queue,
2887 NT_PRINTER_INFO_LEVEL *printer,
2888 TALLOC_CTX *mem_ctx)
2890 char *p;
2892 if (*printer->info_2->comment == '\0') {
2893 p = lp_comment(snum);
2894 } else {
2895 p = printer->info_2->comment;
2898 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2901 /*******************************************************************
2902 * fill a notify_info_data with the comment
2903 * location = "Room 1, floor 2, building 3"
2904 ********************************************************************/
2906 void spoolss_notify_location(int snum,
2907 struct spoolss_Notify *data,
2908 print_queue_struct *queue,
2909 NT_PRINTER_INFO_LEVEL *printer,
2910 TALLOC_CTX *mem_ctx)
2912 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2915 /*******************************************************************
2916 * fill a notify_info_data with the device mode
2917 * jfm:xxxx don't to it for know but that's a real problem !!!
2918 ********************************************************************/
2920 static void spoolss_notify_devmode(int snum,
2921 struct spoolss_Notify *data,
2922 print_queue_struct *queue,
2923 NT_PRINTER_INFO_LEVEL *printer,
2924 TALLOC_CTX *mem_ctx)
2926 /* for a dummy implementation we have to zero the fields */
2927 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2930 /*******************************************************************
2931 * fill a notify_info_data with the separator file name
2932 ********************************************************************/
2934 void spoolss_notify_sepfile(int snum,
2935 struct spoolss_Notify *data,
2936 print_queue_struct *queue,
2937 NT_PRINTER_INFO_LEVEL *printer,
2938 TALLOC_CTX *mem_ctx)
2940 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2943 /*******************************************************************
2944 * fill a notify_info_data with the print processor
2945 * jfm:xxxx return always winprint to indicate we don't do anything to it
2946 ********************************************************************/
2948 void spoolss_notify_print_processor(int snum,
2949 struct spoolss_Notify *data,
2950 print_queue_struct *queue,
2951 NT_PRINTER_INFO_LEVEL *printer,
2952 TALLOC_CTX *mem_ctx)
2954 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2957 /*******************************************************************
2958 * fill a notify_info_data with the print processor options
2959 * jfm:xxxx send an empty string
2960 ********************************************************************/
2962 void spoolss_notify_parameters(int snum,
2963 struct spoolss_Notify *data,
2964 print_queue_struct *queue,
2965 NT_PRINTER_INFO_LEVEL *printer,
2966 TALLOC_CTX *mem_ctx)
2968 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2971 /*******************************************************************
2972 * fill a notify_info_data with the data type
2973 * jfm:xxxx always send RAW as data type
2974 ********************************************************************/
2976 void spoolss_notify_datatype(int snum,
2977 struct spoolss_Notify *data,
2978 print_queue_struct *queue,
2979 NT_PRINTER_INFO_LEVEL *printer,
2980 TALLOC_CTX *mem_ctx)
2982 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2985 /*******************************************************************
2986 * fill a notify_info_data with the security descriptor
2987 * jfm:xxxx send an null pointer to say no security desc
2988 * have to implement security before !
2989 ********************************************************************/
2991 static void spoolss_notify_security_desc(int snum,
2992 struct spoolss_Notify *data,
2993 print_queue_struct *queue,
2994 NT_PRINTER_INFO_LEVEL *printer,
2995 TALLOC_CTX *mem_ctx)
2997 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2998 printer->info_2->secdesc_buf->sd_size,
2999 printer->info_2->secdesc_buf->sd);
3002 /*******************************************************************
3003 * fill a notify_info_data with the attributes
3004 * jfm:xxxx a samba printer is always shared
3005 ********************************************************************/
3007 void spoolss_notify_attributes(int snum,
3008 struct spoolss_Notify *data,
3009 print_queue_struct *queue,
3010 NT_PRINTER_INFO_LEVEL *printer,
3011 TALLOC_CTX *mem_ctx)
3013 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3016 /*******************************************************************
3017 * fill a notify_info_data with the priority
3018 ********************************************************************/
3020 static void spoolss_notify_priority(int snum,
3021 struct spoolss_Notify *data,
3022 print_queue_struct *queue,
3023 NT_PRINTER_INFO_LEVEL *printer,
3024 TALLOC_CTX *mem_ctx)
3026 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3029 /*******************************************************************
3030 * fill a notify_info_data with the default priority
3031 ********************************************************************/
3033 static void spoolss_notify_default_priority(int snum,
3034 struct spoolss_Notify *data,
3035 print_queue_struct *queue,
3036 NT_PRINTER_INFO_LEVEL *printer,
3037 TALLOC_CTX *mem_ctx)
3039 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3042 /*******************************************************************
3043 * fill a notify_info_data with the start time
3044 ********************************************************************/
3046 static void spoolss_notify_start_time(int snum,
3047 struct spoolss_Notify *data,
3048 print_queue_struct *queue,
3049 NT_PRINTER_INFO_LEVEL *printer,
3050 TALLOC_CTX *mem_ctx)
3052 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3055 /*******************************************************************
3056 * fill a notify_info_data with the until time
3057 ********************************************************************/
3059 static void spoolss_notify_until_time(int snum,
3060 struct spoolss_Notify *data,
3061 print_queue_struct *queue,
3062 NT_PRINTER_INFO_LEVEL *printer,
3063 TALLOC_CTX *mem_ctx)
3065 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3068 /*******************************************************************
3069 * fill a notify_info_data with the status
3070 ********************************************************************/
3072 static void spoolss_notify_status(int snum,
3073 struct spoolss_Notify *data,
3074 print_queue_struct *queue,
3075 NT_PRINTER_INFO_LEVEL *printer,
3076 TALLOC_CTX *mem_ctx)
3078 print_status_struct status;
3080 print_queue_length(snum, &status);
3081 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3084 /*******************************************************************
3085 * fill a notify_info_data with the number of jobs queued
3086 ********************************************************************/
3088 void spoolss_notify_cjobs(int snum,
3089 struct spoolss_Notify *data,
3090 print_queue_struct *queue,
3091 NT_PRINTER_INFO_LEVEL *printer,
3092 TALLOC_CTX *mem_ctx)
3094 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3097 /*******************************************************************
3098 * fill a notify_info_data with the average ppm
3099 ********************************************************************/
3101 static void spoolss_notify_average_ppm(int snum,
3102 struct spoolss_Notify *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 /* always respond 8 pages per minutes */
3108 /* a little hard ! */
3109 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3112 /*******************************************************************
3113 * fill a notify_info_data with username
3114 ********************************************************************/
3116 static void spoolss_notify_username(int snum,
3117 struct spoolss_Notify *data,
3118 print_queue_struct *queue,
3119 NT_PRINTER_INFO_LEVEL *printer,
3120 TALLOC_CTX *mem_ctx)
3122 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3125 /*******************************************************************
3126 * fill a notify_info_data with job status
3127 ********************************************************************/
3129 static void spoolss_notify_job_status(int snum,
3130 struct spoolss_Notify *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3135 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3138 /*******************************************************************
3139 * fill a notify_info_data with job name
3140 ********************************************************************/
3142 static void spoolss_notify_job_name(int snum,
3143 struct spoolss_Notify *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3148 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3151 /*******************************************************************
3152 * fill a notify_info_data with job status
3153 ********************************************************************/
3155 static void spoolss_notify_job_status_string(int snum,
3156 struct spoolss_Notify *data,
3157 print_queue_struct *queue,
3158 NT_PRINTER_INFO_LEVEL *printer,
3159 TALLOC_CTX *mem_ctx)
3162 * Now we're returning job status codes we just return a "" here. JRA.
3165 const char *p = "";
3167 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3168 p = "unknown";
3170 switch (queue->status) {
3171 case LPQ_QUEUED:
3172 p = "Queued";
3173 break;
3174 case LPQ_PAUSED:
3175 p = ""; /* NT provides the paused string */
3176 break;
3177 case LPQ_SPOOLING:
3178 p = "Spooling";
3179 break;
3180 case LPQ_PRINTING:
3181 p = "Printing";
3182 break;
3184 #endif /* NO LONGER NEEDED. */
3186 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3189 /*******************************************************************
3190 * fill a notify_info_data with job time
3191 ********************************************************************/
3193 static void spoolss_notify_job_time(int snum,
3194 struct spoolss_Notify *data,
3195 print_queue_struct *queue,
3196 NT_PRINTER_INFO_LEVEL *printer,
3197 TALLOC_CTX *mem_ctx)
3199 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3202 /*******************************************************************
3203 * fill a notify_info_data with job size
3204 ********************************************************************/
3206 static void spoolss_notify_job_size(int snum,
3207 struct spoolss_Notify *data,
3208 print_queue_struct *queue,
3209 NT_PRINTER_INFO_LEVEL *printer,
3210 TALLOC_CTX *mem_ctx)
3212 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3215 /*******************************************************************
3216 * fill a notify_info_data with page info
3217 ********************************************************************/
3218 static void spoolss_notify_total_pages(int snum,
3219 struct spoolss_Notify *data,
3220 print_queue_struct *queue,
3221 NT_PRINTER_INFO_LEVEL *printer,
3222 TALLOC_CTX *mem_ctx)
3224 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3227 /*******************************************************************
3228 * fill a notify_info_data with pages printed info.
3229 ********************************************************************/
3230 static void spoolss_notify_pages_printed(int snum,
3231 struct spoolss_Notify *data,
3232 print_queue_struct *queue,
3233 NT_PRINTER_INFO_LEVEL *printer,
3234 TALLOC_CTX *mem_ctx)
3236 /* Add code when back-end tracks this */
3237 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3240 /*******************************************************************
3241 Fill a notify_info_data with job position.
3242 ********************************************************************/
3244 static void spoolss_notify_job_position(int snum,
3245 struct spoolss_Notify *data,
3246 print_queue_struct *queue,
3247 NT_PRINTER_INFO_LEVEL *printer,
3248 TALLOC_CTX *mem_ctx)
3250 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3253 /*******************************************************************
3254 Fill a notify_info_data with submitted time.
3255 ********************************************************************/
3257 static void spoolss_notify_submitted_time(int snum,
3258 struct spoolss_Notify *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3263 data->data.string.string = NULL;
3264 data->data.string.size = 0;
3266 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3267 &data->data.string.string,
3268 &data->data.string.size);
3272 struct s_notify_info_data_table
3274 enum spoolss_NotifyType type;
3275 uint16_t field;
3276 const char *name;
3277 enum spoolss_NotifyTable variable_type;
3278 void (*fn) (int snum, struct spoolss_Notify *data,
3279 print_queue_struct *queue,
3280 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3283 /* A table describing the various print notification constants and
3284 whether the notification data is a pointer to a variable sized
3285 buffer, a one value uint32_t or a two value uint32_t. */
3287 static const struct s_notify_info_data_table notify_info_data_table[] =
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3340 /*******************************************************************
3341 Return the variable_type of info_data structure.
3342 ********************************************************************/
3344 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3345 uint16_t field)
3347 int i=0;
3349 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3350 if ( (notify_info_data_table[i].type == type) &&
3351 (notify_info_data_table[i].field == field) ) {
3352 return notify_info_data_table[i].variable_type;
3356 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3358 return 0;
3361 /****************************************************************************
3362 ****************************************************************************/
3364 static bool search_notify(enum spoolss_NotifyType type,
3365 uint16_t field,
3366 int *value)
3368 int i;
3370 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3371 if (notify_info_data_table[i].type == type &&
3372 notify_info_data_table[i].field == field &&
3373 notify_info_data_table[i].fn != NULL) {
3374 *value = i;
3375 return true;
3379 return false;
3382 /****************************************************************************
3383 ****************************************************************************/
3385 void construct_info_data(struct spoolss_Notify *info_data,
3386 enum spoolss_NotifyType type,
3387 uint16_t field,
3388 int id)
3390 info_data->type = type;
3391 info_data->field.field = field;
3392 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3393 info_data->job_id = id;
3396 /*******************************************************************
3398 * fill a notify_info struct with info asked
3400 ********************************************************************/
3402 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3403 struct spoolss_NotifyInfo *info,
3404 int snum,
3405 const struct spoolss_NotifyOptionType *option_type,
3406 uint32_t id,
3407 TALLOC_CTX *mem_ctx)
3409 int field_num,j;
3410 enum spoolss_NotifyType type;
3411 uint16_t field;
3413 struct spoolss_Notify *current_data;
3414 NT_PRINTER_INFO_LEVEL *printer = NULL;
3415 print_queue_struct *queue=NULL;
3417 type = option_type->type;
3419 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3420 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3421 option_type->count, lp_servicename(snum)));
3423 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3424 return false;
3426 for(field_num=0; field_num < option_type->count; field_num++) {
3427 field = option_type->fields[field_num].field;
3429 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3431 if (!search_notify(type, field, &j) )
3432 continue;
3434 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3435 struct spoolss_Notify,
3436 info->count + 1);
3437 if (info->notifies == NULL) {
3438 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3439 free_a_printer(&printer, 2);
3440 return false;
3443 current_data = &info->notifies[info->count];
3445 construct_info_data(current_data, type, field, id);
3447 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3448 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3450 notify_info_data_table[j].fn(snum, current_data, queue,
3451 printer, mem_ctx);
3453 info->count++;
3456 free_a_printer(&printer, 2);
3457 return true;
3460 /*******************************************************************
3462 * fill a notify_info struct with info asked
3464 ********************************************************************/
3466 static bool construct_notify_jobs_info(print_queue_struct *queue,
3467 struct spoolss_NotifyInfo *info,
3468 NT_PRINTER_INFO_LEVEL *printer,
3469 int snum,
3470 const struct spoolss_NotifyOptionType *option_type,
3471 uint32_t id,
3472 TALLOC_CTX *mem_ctx)
3474 int field_num,j;
3475 enum spoolss_NotifyType type;
3476 uint16_t field;
3477 struct spoolss_Notify *current_data;
3479 DEBUG(4,("construct_notify_jobs_info\n"));
3481 type = option_type->type;
3483 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3484 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3485 option_type->count));
3487 for(field_num=0; field_num<option_type->count; field_num++) {
3488 field = option_type->fields[field_num].field;
3490 if (!search_notify(type, field, &j) )
3491 continue;
3493 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3494 struct spoolss_Notify,
3495 info->count + 1);
3496 if (info->notifies == NULL) {
3497 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3498 return false;
3501 current_data=&(info->notifies[info->count]);
3503 construct_info_data(current_data, type, field, id);
3504 notify_info_data_table[j].fn(snum, current_data, queue,
3505 printer, mem_ctx);
3506 info->count++;
3509 return true;
3513 * JFM: The enumeration is not that simple, it's even non obvious.
3515 * let's take an example: I want to monitor the PRINTER SERVER for
3516 * the printer's name and the number of jobs currently queued.
3517 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3518 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3520 * I have 3 printers on the back of my server.
3522 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3523 * structures.
3524 * Number Data Id
3525 * 1 printer 1 name 1
3526 * 2 printer 1 cjob 1
3527 * 3 printer 2 name 2
3528 * 4 printer 2 cjob 2
3529 * 5 printer 3 name 3
3530 * 6 printer 3 name 3
3532 * that's the print server case, the printer case is even worse.
3535 /*******************************************************************
3537 * enumerate all printers on the printserver
3538 * fill a notify_info struct with info asked
3540 ********************************************************************/
3542 static WERROR printserver_notify_info(pipes_struct *p,
3543 struct policy_handle *hnd,
3544 struct spoolss_NotifyInfo *info,
3545 TALLOC_CTX *mem_ctx)
3547 int snum;
3548 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3549 int n_services=lp_numservices();
3550 int i;
3551 struct spoolss_NotifyOption *option;
3552 struct spoolss_NotifyOptionType option_type;
3554 DEBUG(4,("printserver_notify_info\n"));
3556 if (!Printer)
3557 return WERR_BADFID;
3559 option = Printer->notify.option;
3561 info->version = 2;
3562 info->notifies = NULL;
3563 info->count = 0;
3565 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3566 sending a ffpcn() request first */
3568 if ( !option )
3569 return WERR_BADFID;
3571 for (i=0; i<option->count; i++) {
3572 option_type = option->types[i];
3574 if (option_type.type != PRINTER_NOTIFY_TYPE)
3575 continue;
3577 for (snum=0; snum<n_services; snum++)
3579 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3580 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3584 #if 0
3586 * Debugging information, don't delete.
3589 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3590 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3591 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3593 for (i=0; i<info->count; i++) {
3594 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3595 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3596 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3598 #endif
3600 return WERR_OK;
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3610 struct spoolss_NotifyInfo *info,
3611 TALLOC_CTX *mem_ctx)
3613 int snum;
3614 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3615 int i;
3616 uint32_t id;
3617 struct spoolss_NotifyOption *option;
3618 struct spoolss_NotifyOptionType option_type;
3619 int count,j;
3620 print_queue_struct *queue=NULL;
3621 print_status_struct status;
3623 DEBUG(4,("printer_notify_info\n"));
3625 if (!Printer)
3626 return WERR_BADFID;
3628 option = Printer->notify.option;
3629 id = 0x0;
3631 info->version = 2;
3632 info->notifies = NULL;
3633 info->count = 0;
3635 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3636 sending a ffpcn() request first */
3638 if ( !option )
3639 return WERR_BADFID;
3641 get_printer_snum(p, hnd, &snum, NULL);
3643 for (i=0; i<option->count; i++) {
3644 option_type = option->types[i];
3646 switch (option_type.type) {
3647 case PRINTER_NOTIFY_TYPE:
3648 if(construct_notify_printer_info(Printer, info, snum,
3649 &option_type, id,
3650 mem_ctx))
3651 id--;
3652 break;
3654 case JOB_NOTIFY_TYPE: {
3655 NT_PRINTER_INFO_LEVEL *printer = NULL;
3657 count = print_queue_status(snum, &queue, &status);
3659 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3660 goto done;
3662 for (j=0; j<count; j++) {
3663 construct_notify_jobs_info(&queue[j], info,
3664 printer, snum,
3665 &option_type,
3666 queue[j].job,
3667 mem_ctx);
3670 free_a_printer(&printer, 2);
3672 done:
3673 SAFE_FREE(queue);
3674 break;
3680 * Debugging information, don't delete.
3683 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3684 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3685 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3687 for (i=0; i<info->count; i++) {
3688 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3689 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3690 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3693 return WERR_OK;
3696 /****************************************************************
3697 _spoolss_RouterRefreshPrinterChangeNotify
3698 ****************************************************************/
3700 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3701 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3703 struct spoolss_NotifyInfo *info;
3705 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3706 WERROR result = WERR_BADFID;
3708 /* we always have a spoolss_NotifyInfo struct */
3709 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3710 if (!info) {
3711 result = WERR_NOMEM;
3712 goto done;
3715 *r->out.info = info;
3717 if (!Printer) {
3718 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3719 "Invalid handle (%s:%u:%u).\n",
3720 OUR_HANDLE(r->in.handle)));
3721 goto done;
3724 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3727 * We are now using the change value, and
3728 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3729 * I don't have a global notification system, I'm sending back all the
3730 * informations even when _NOTHING_ has changed.
3733 /* We need to keep track of the change value to send back in
3734 RRPCN replies otherwise our updates are ignored. */
3736 Printer->notify.fnpcn = true;
3738 if (Printer->notify.client_connected) {
3739 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3740 "Saving change value in request [%x]\n",
3741 r->in.change_low));
3742 Printer->notify.change = r->in.change_low;
3745 /* just ignore the spoolss_NotifyOption */
3747 switch (Printer->printer_type) {
3748 case SPLHND_SERVER:
3749 result = printserver_notify_info(p, r->in.handle,
3750 info, p->mem_ctx);
3751 break;
3753 case SPLHND_PRINTER:
3754 result = printer_notify_info(p, r->in.handle,
3755 info, p->mem_ctx);
3756 break;
3759 Printer->notify.fnpcn = false;
3761 done:
3762 return result;
3765 /********************************************************************
3766 * construct_printer_info_0
3767 * fill a printer_info_0 struct
3768 ********************************************************************/
3770 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3771 const NT_PRINTER_INFO_LEVEL *ntprinter,
3772 struct spoolss_PrinterInfo0 *r,
3773 int snum)
3775 int count;
3776 counter_printer_0 *session_counter;
3777 time_t setuptime;
3778 print_status_struct status;
3780 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3781 W_ERROR_HAVE_NO_MEMORY(r->printername);
3783 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3784 W_ERROR_HAVE_NO_MEMORY(r->servername);
3786 count = print_queue_length(snum, &status);
3788 /* check if we already have a counter for this printer */
3789 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3790 if (session_counter->snum == snum)
3791 break;
3794 /* it's the first time, add it to the list */
3795 if (session_counter == NULL) {
3796 session_counter = SMB_MALLOC_P(counter_printer_0);
3797 W_ERROR_HAVE_NO_MEMORY(session_counter);
3798 ZERO_STRUCTP(session_counter);
3799 session_counter->snum = snum;
3800 session_counter->counter = 0;
3801 DLIST_ADD(counter_list, session_counter);
3804 /* increment it */
3805 session_counter->counter++;
3807 r->cjobs = count;
3808 r->total_jobs = 0;
3809 r->total_bytes = 0;
3811 setuptime = (time_t)ntprinter->info_2->setuptime;
3813 init_systemtime(&r->time, gmtime(&setuptime));
3815 /* JFM:
3816 * the global_counter should be stored in a TDB as it's common to all the clients
3817 * and should be zeroed on samba startup
3819 r->global_counter = session_counter->counter;
3820 r->total_pages = 0;
3821 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3822 r->version = 0x0005; /* NT 5 */
3823 r->free_build = 0x0893; /* build 2195 */
3824 r->spooling = 0;
3825 r->max_spooling = 0;
3826 r->session_counter = session_counter->counter;
3827 r->num_error_out_of_paper = 0x0;
3828 r->num_error_not_ready = 0x0; /* number of print failure */
3829 r->job_error = 0x0;
3830 r->number_of_processors = 0x1;
3831 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3832 r->high_part_total_bytes = 0x0;
3833 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3834 r->last_error = WERR_OK;
3835 r->status = nt_printq_status(status.status);
3836 r->enumerate_network_printers = 0x0;
3837 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3838 r->processor_architecture = 0x0;
3839 r->processor_level = 0x6; /* 6 ???*/
3840 r->ref_ic = 0;
3841 r->reserved2 = 0;
3842 r->reserved3 = 0;
3844 return WERR_OK;
3847 /****************************************************************************
3848 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3849 should be valid upon entry
3850 ****************************************************************************/
3852 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3853 struct spoolss_DeviceMode *r,
3854 const NT_DEVICEMODE *ntdevmode)
3856 if (!r || !ntdevmode) {
3857 return WERR_INVALID_PARAM;
3860 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3861 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3863 r->specversion = ntdevmode->specversion;
3864 r->driverversion = ntdevmode->driverversion;
3865 r->size = ntdevmode->size;
3866 r->__driverextra_length = ntdevmode->driverextra;
3867 r->fields = ntdevmode->fields;
3869 r->orientation = ntdevmode->orientation;
3870 r->papersize = ntdevmode->papersize;
3871 r->paperlength = ntdevmode->paperlength;
3872 r->paperwidth = ntdevmode->paperwidth;
3873 r->scale = ntdevmode->scale;
3874 r->copies = ntdevmode->copies;
3875 r->defaultsource = ntdevmode->defaultsource;
3876 r->printquality = ntdevmode->printquality;
3877 r->color = ntdevmode->color;
3878 r->duplex = ntdevmode->duplex;
3879 r->yresolution = ntdevmode->yresolution;
3880 r->ttoption = ntdevmode->ttoption;
3881 r->collate = ntdevmode->collate;
3883 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3884 W_ERROR_HAVE_NO_MEMORY(r->formname);
3886 /* all 0 below are values that have not been set in the old parsing/copy
3887 * function, maybe they should... - gd */
3889 r->logpixels = 0;
3890 r->bitsperpel = 0;
3891 r->pelswidth = 0;
3892 r->pelsheight = 0;
3893 r->displayflags = 0;
3894 r->displayfrequency = 0;
3895 r->icmmethod = ntdevmode->icmmethod;
3896 r->icmintent = ntdevmode->icmintent;
3897 r->mediatype = ntdevmode->mediatype;
3898 r->dithertype = ntdevmode->dithertype;
3899 r->reserved1 = 0;
3900 r->reserved2 = 0;
3901 r->panningwidth = 0;
3902 r->panningheight = 0;
3904 if (ntdevmode->nt_dev_private != NULL) {
3905 r->driverextra_data = data_blob_talloc(mem_ctx,
3906 ntdevmode->nt_dev_private,
3907 ntdevmode->driverextra);
3908 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3911 return WERR_OK;
3915 /****************************************************************************
3916 Create a spoolss_DeviceMode struct. Returns talloced memory.
3917 ****************************************************************************/
3919 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3920 const char *servicename)
3922 WERROR result;
3923 NT_PRINTER_INFO_LEVEL *printer = NULL;
3924 struct spoolss_DeviceMode *devmode = NULL;
3926 DEBUG(7,("construct_dev_mode\n"));
3928 DEBUGADD(8,("getting printer characteristics\n"));
3930 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3931 return NULL;
3933 if (!printer->info_2->devmode) {
3934 DEBUG(5, ("BONG! There was no device mode!\n"));
3935 goto done;
3938 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3939 if (!devmode) {
3940 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3941 goto done;
3944 DEBUGADD(8,("loading DEVICEMODE\n"));
3946 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3947 if (!W_ERROR_IS_OK(result)) {
3948 TALLOC_FREE(devmode);
3951 done:
3952 free_a_printer(&printer,2);
3954 return devmode;
3957 /********************************************************************
3958 * construct_printer_info3
3959 * fill a spoolss_PrinterInfo3 struct
3960 ********************************************************************/
3962 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3963 const NT_PRINTER_INFO_LEVEL *ntprinter,
3964 struct spoolss_PrinterInfo3 *r,
3965 int snum)
3967 /* These are the components of the SD we are returning. */
3969 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3970 /* don't use talloc_steal() here unless you do a deep steal of all
3971 the SEC_DESC members */
3973 r->secdesc = dup_sec_desc(mem_ctx,
3974 ntprinter->info_2->secdesc_buf->sd);
3975 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3978 return WERR_OK;
3981 /********************************************************************
3982 * construct_printer_info4
3983 * fill a spoolss_PrinterInfo4 struct
3984 ********************************************************************/
3986 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3987 const NT_PRINTER_INFO_LEVEL *ntprinter,
3988 struct spoolss_PrinterInfo4 *r,
3989 int snum)
3991 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3992 W_ERROR_HAVE_NO_MEMORY(r->printername);
3993 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3994 W_ERROR_HAVE_NO_MEMORY(r->servername);
3996 r->attributes = ntprinter->info_2->attributes;
3998 return WERR_OK;
4001 /********************************************************************
4002 * construct_printer_info5
4003 * fill a spoolss_PrinterInfo5 struct
4004 ********************************************************************/
4006 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4007 const NT_PRINTER_INFO_LEVEL *ntprinter,
4008 struct spoolss_PrinterInfo5 *r,
4009 int snum)
4011 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4012 W_ERROR_HAVE_NO_MEMORY(r->printername);
4013 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4014 W_ERROR_HAVE_NO_MEMORY(r->portname);
4016 r->attributes = ntprinter->info_2->attributes;
4018 /* these two are not used by NT+ according to MSDN */
4020 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4021 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4023 return WERR_OK;
4026 /********************************************************************
4027 * construct_printer_info_6
4028 * fill a spoolss_PrinterInfo6 struct
4029 ********************************************************************/
4031 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4032 const NT_PRINTER_INFO_LEVEL *ntprinter,
4033 struct spoolss_PrinterInfo6 *r,
4034 int snum)
4036 int count;
4037 print_status_struct status;
4039 count = print_queue_length(snum, &status);
4041 r->status = nt_printq_status(status.status);
4043 return WERR_OK;
4046 /********************************************************************
4047 * construct_printer_info7
4048 * fill a spoolss_PrinterInfo7 struct
4049 ********************************************************************/
4051 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4052 Printer_entry *print_hnd,
4053 struct spoolss_PrinterInfo7 *r,
4054 int snum)
4056 struct GUID guid;
4058 if (is_printer_published(print_hnd, snum, &guid)) {
4059 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4060 r->action = DSPRINT_PUBLISH;
4061 } else {
4062 r->guid = talloc_strdup(mem_ctx, "");
4063 r->action = DSPRINT_UNPUBLISH;
4065 W_ERROR_HAVE_NO_MEMORY(r->guid);
4067 return WERR_OK;
4070 /********************************************************************
4071 * construct_printer_info8
4072 * fill a spoolss_PrinterInfo8 struct
4073 ********************************************************************/
4075 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4076 const NT_PRINTER_INFO_LEVEL *ntprinter,
4077 struct spoolss_DeviceModeInfo *r,
4078 int snum)
4080 struct spoolss_DeviceMode *devmode;
4081 WERROR result;
4083 if (!ntprinter->info_2->devmode) {
4084 r->devmode = NULL;
4085 return WERR_OK;
4088 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4089 W_ERROR_HAVE_NO_MEMORY(devmode);
4091 result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4092 if (!W_ERROR_IS_OK(result)) {
4093 TALLOC_FREE(devmode);
4094 return result;
4097 r->devmode = devmode;
4099 return WERR_OK;
4103 /********************************************************************
4104 * construct_printer_info1
4105 * fill a spoolss_PrinterInfo1 struct
4106 ********************************************************************/
4108 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4109 const NT_PRINTER_INFO_LEVEL *ntprinter,
4110 uint32_t flags,
4111 struct spoolss_PrinterInfo1 *r,
4112 int snum)
4114 r->flags = flags;
4116 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4117 ntprinter->info_2->printername,
4118 ntprinter->info_2->drivername,
4119 ntprinter->info_2->location);
4120 W_ERROR_HAVE_NO_MEMORY(r->description);
4122 if (*ntprinter->info_2->comment == '\0') {
4123 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4124 } else {
4125 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4127 W_ERROR_HAVE_NO_MEMORY(r->comment);
4129 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4130 W_ERROR_HAVE_NO_MEMORY(r->name);
4132 return WERR_OK;
4135 /********************************************************************
4136 * construct_printer_info2
4137 * fill a spoolss_PrinterInfo2 struct
4138 ********************************************************************/
4140 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4141 const NT_PRINTER_INFO_LEVEL *ntprinter,
4142 struct spoolss_PrinterInfo2 *r,
4143 int snum)
4145 int count;
4147 print_status_struct status;
4149 count = print_queue_length(snum, &status);
4151 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4152 W_ERROR_HAVE_NO_MEMORY(r->servername);
4153 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4154 W_ERROR_HAVE_NO_MEMORY(r->printername);
4155 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4156 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4157 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4158 W_ERROR_HAVE_NO_MEMORY(r->portname);
4159 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4160 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4162 if (*ntprinter->info_2->comment == '\0') {
4163 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4164 } else {
4165 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4167 W_ERROR_HAVE_NO_MEMORY(r->comment);
4169 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4170 W_ERROR_HAVE_NO_MEMORY(r->location);
4171 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4172 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4173 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4174 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4175 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4176 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4177 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4178 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4180 r->attributes = ntprinter->info_2->attributes;
4182 r->priority = ntprinter->info_2->priority;
4183 r->defaultpriority = ntprinter->info_2->default_priority;
4184 r->starttime = ntprinter->info_2->starttime;
4185 r->untiltime = ntprinter->info_2->untiltime;
4186 r->status = nt_printq_status(status.status);
4187 r->cjobs = count;
4188 r->averageppm = ntprinter->info_2->averageppm;
4190 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4191 if (!r->devmode) {
4192 DEBUG(8,("Returning NULL Devicemode!\n"));
4195 r->secdesc = NULL;
4197 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4198 /* don't use talloc_steal() here unless you do a deep steal of all
4199 the SEC_DESC members */
4201 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4204 return WERR_OK;
4207 /********************************************************************
4208 ********************************************************************/
4210 static bool snum_is_shared_printer(int snum)
4212 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4215 /********************************************************************
4216 Spoolss_enumprinters.
4217 ********************************************************************/
4219 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4220 uint32_t level,
4221 uint32_t flags,
4222 union spoolss_PrinterInfo **info_p,
4223 uint32_t *count_p)
4225 int snum;
4226 int n_services = lp_numservices();
4227 union spoolss_PrinterInfo *info = NULL;
4228 uint32_t count = 0;
4229 WERROR result = WERR_OK;
4231 *count_p = 0;
4232 *info_p = NULL;
4234 for (snum = 0; snum < n_services; snum++) {
4236 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4238 if (!snum_is_shared_printer(snum)) {
4239 continue;
4242 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4243 lp_servicename(snum), snum));
4245 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4246 union spoolss_PrinterInfo,
4247 count + 1);
4248 if (!info) {
4249 result = WERR_NOMEM;
4250 goto out;
4253 result = get_a_printer(NULL, &ntprinter, 2,
4254 lp_const_servicename(snum));
4255 if (!W_ERROR_IS_OK(result)) {
4256 goto out;
4259 switch (level) {
4260 case 0:
4261 result = construct_printer_info0(info, ntprinter,
4262 &info[count].info0, snum);
4263 break;
4264 case 1:
4265 result = construct_printer_info1(info, ntprinter, flags,
4266 &info[count].info1, snum);
4267 break;
4268 case 2:
4269 result = construct_printer_info2(info, ntprinter,
4270 &info[count].info2, snum);
4271 break;
4272 case 4:
4273 result = construct_printer_info4(info, ntprinter,
4274 &info[count].info4, snum);
4275 break;
4276 case 5:
4277 result = construct_printer_info5(info, ntprinter,
4278 &info[count].info5, snum);
4279 break;
4281 default:
4282 result = WERR_UNKNOWN_LEVEL;
4283 free_a_printer(&ntprinter, 2);
4284 goto out;
4287 free_a_printer(&ntprinter, 2);
4288 if (!W_ERROR_IS_OK(result)) {
4289 goto out;
4292 count++;
4295 *count_p = count;
4296 *info_p = info;
4298 out:
4299 if (!W_ERROR_IS_OK(result)) {
4300 TALLOC_FREE(info);
4301 return result;
4304 *info_p = info;
4306 return WERR_OK;
4309 /********************************************************************
4310 * handle enumeration of printers at level 0
4311 ********************************************************************/
4313 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4314 uint32_t flags,
4315 const char *servername,
4316 union spoolss_PrinterInfo **info,
4317 uint32_t *count)
4319 DEBUG(4,("enum_all_printers_info_0\n"));
4321 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4325 /********************************************************************
4326 ********************************************************************/
4328 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4329 uint32_t flags,
4330 union spoolss_PrinterInfo **info,
4331 uint32_t *count)
4333 DEBUG(4,("enum_all_printers_info_1\n"));
4335 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4338 /********************************************************************
4339 enum_all_printers_info_1_local.
4340 *********************************************************************/
4342 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4343 union spoolss_PrinterInfo **info,
4344 uint32_t *count)
4346 DEBUG(4,("enum_all_printers_info_1_local\n"));
4348 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4351 /********************************************************************
4352 enum_all_printers_info_1_name.
4353 *********************************************************************/
4355 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4356 const char *name,
4357 union spoolss_PrinterInfo **info,
4358 uint32_t *count)
4360 const char *s = name;
4362 DEBUG(4,("enum_all_printers_info_1_name\n"));
4364 if ((name[0] == '\\') && (name[1] == '\\')) {
4365 s = name + 2;
4368 if (!is_myname_or_ipaddr(s)) {
4369 return WERR_INVALID_NAME;
4372 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4375 /********************************************************************
4376 enum_all_printers_info_1_network.
4377 *********************************************************************/
4379 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4380 const char *name,
4381 union spoolss_PrinterInfo **info,
4382 uint32_t *count)
4384 const char *s = name;
4386 DEBUG(4,("enum_all_printers_info_1_network\n"));
4388 /* If we respond to a enum_printers level 1 on our name with flags
4389 set to PRINTER_ENUM_REMOTE with a list of printers then these
4390 printers incorrectly appear in the APW browse list.
4391 Specifically the printers for the server appear at the workgroup
4392 level where all the other servers in the domain are
4393 listed. Windows responds to this call with a
4394 WERR_CAN_NOT_COMPLETE so we should do the same. */
4396 if (name[0] == '\\' && name[1] == '\\') {
4397 s = name + 2;
4400 if (is_myname_or_ipaddr(s)) {
4401 return WERR_CAN_NOT_COMPLETE;
4404 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4407 /********************************************************************
4408 * api_spoolss_enumprinters
4410 * called from api_spoolss_enumprinters (see this to understand)
4411 ********************************************************************/
4413 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4414 union spoolss_PrinterInfo **info,
4415 uint32_t *count)
4417 DEBUG(4,("enum_all_printers_info_2\n"));
4419 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4422 /********************************************************************
4423 * handle enumeration of printers at level 1
4424 ********************************************************************/
4426 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4427 uint32_t flags,
4428 const char *name,
4429 union spoolss_PrinterInfo **info,
4430 uint32_t *count)
4432 /* Not all the flags are equals */
4434 if (flags & PRINTER_ENUM_LOCAL) {
4435 return enum_all_printers_info_1_local(mem_ctx, info, count);
4438 if (flags & PRINTER_ENUM_NAME) {
4439 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4442 if (flags & PRINTER_ENUM_NETWORK) {
4443 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4446 return WERR_OK; /* NT4sp5 does that */
4449 /********************************************************************
4450 * handle enumeration of printers at level 2
4451 ********************************************************************/
4453 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4454 uint32_t flags,
4455 const char *servername,
4456 union spoolss_PrinterInfo **info,
4457 uint32_t *count)
4459 if (flags & PRINTER_ENUM_LOCAL) {
4460 return enum_all_printers_info_2(mem_ctx, info, count);
4463 if (flags & PRINTER_ENUM_NAME) {
4464 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4465 return WERR_INVALID_NAME;
4468 return enum_all_printers_info_2(mem_ctx, info, count);
4471 if (flags & PRINTER_ENUM_REMOTE) {
4472 return WERR_UNKNOWN_LEVEL;
4475 return WERR_OK;
4478 /********************************************************************
4479 * handle enumeration of printers at level 4
4480 ********************************************************************/
4482 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4483 uint32_t flags,
4484 const char *servername,
4485 union spoolss_PrinterInfo **info,
4486 uint32_t *count)
4488 DEBUG(4,("enum_all_printers_info_4\n"));
4490 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4494 /********************************************************************
4495 * handle enumeration of printers at level 5
4496 ********************************************************************/
4498 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4499 uint32_t flags,
4500 const char *servername,
4501 union spoolss_PrinterInfo **info,
4502 uint32_t *count)
4504 DEBUG(4,("enum_all_printers_info_5\n"));
4506 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4509 /****************************************************************
4510 _spoolss_EnumPrinters
4511 ****************************************************************/
4513 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4514 struct spoolss_EnumPrinters *r)
4516 const char *name;
4517 WERROR result;
4519 /* that's an [in out] buffer */
4521 if (!r->in.buffer && (r->in.offered != 0)) {
4522 return WERR_INVALID_PARAM;
4525 DEBUG(4,("_spoolss_EnumPrinters\n"));
4527 *r->out.needed = 0;
4528 *r->out.count = 0;
4529 *r->out.info = NULL;
4532 * Level 1:
4533 * flags==PRINTER_ENUM_NAME
4534 * if name=="" then enumerates all printers
4535 * if name!="" then enumerate the printer
4536 * flags==PRINTER_ENUM_REMOTE
4537 * name is NULL, enumerate printers
4538 * Level 2: name!="" enumerates printers, name can't be NULL
4539 * Level 3: doesn't exist
4540 * Level 4: does a local registry lookup
4541 * Level 5: same as Level 2
4544 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4545 W_ERROR_HAVE_NO_MEMORY(name);
4547 switch (r->in.level) {
4548 case 0:
4549 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4550 r->out.info, r->out.count);
4551 break;
4552 case 1:
4553 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4554 r->out.info, r->out.count);
4555 break;
4556 case 2:
4557 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4558 r->out.info, r->out.count);
4559 break;
4560 case 4:
4561 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4562 r->out.info, r->out.count);
4563 break;
4564 case 5:
4565 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4566 r->out.info, r->out.count);
4567 break;
4568 default:
4569 return WERR_UNKNOWN_LEVEL;
4572 if (!W_ERROR_IS_OK(result)) {
4573 return result;
4576 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4577 spoolss_EnumPrinters, NULL,
4578 *r->out.info, r->in.level,
4579 *r->out.count);
4580 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4581 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4583 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4586 /****************************************************************
4587 _spoolss_GetPrinter
4588 ****************************************************************/
4590 WERROR _spoolss_GetPrinter(pipes_struct *p,
4591 struct spoolss_GetPrinter *r)
4593 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4594 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4595 WERROR result = WERR_OK;
4597 int snum;
4599 /* that's an [in out] buffer */
4601 if (!r->in.buffer && (r->in.offered != 0)) {
4602 return WERR_INVALID_PARAM;
4605 *r->out.needed = 0;
4607 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4608 return WERR_BADFID;
4611 result = get_a_printer(Printer, &ntprinter, 2,
4612 lp_const_servicename(snum));
4613 if (!W_ERROR_IS_OK(result)) {
4614 return result;
4617 switch (r->in.level) {
4618 case 0:
4619 result = construct_printer_info0(p->mem_ctx, ntprinter,
4620 &r->out.info->info0, snum);
4621 break;
4622 case 1:
4623 result = construct_printer_info1(p->mem_ctx, ntprinter,
4624 PRINTER_ENUM_ICON8,
4625 &r->out.info->info1, snum);
4626 break;
4627 case 2:
4628 result = construct_printer_info2(p->mem_ctx, ntprinter,
4629 &r->out.info->info2, snum);
4630 break;
4631 case 3:
4632 result = construct_printer_info3(p->mem_ctx, ntprinter,
4633 &r->out.info->info3, snum);
4634 break;
4635 case 4:
4636 result = construct_printer_info4(p->mem_ctx, ntprinter,
4637 &r->out.info->info4, snum);
4638 break;
4639 case 5:
4640 result = construct_printer_info5(p->mem_ctx, ntprinter,
4641 &r->out.info->info5, snum);
4642 break;
4643 case 6:
4644 result = construct_printer_info6(p->mem_ctx, ntprinter,
4645 &r->out.info->info6, snum);
4646 break;
4647 case 7:
4648 result = construct_printer_info7(p->mem_ctx, Printer,
4649 &r->out.info->info7, snum);
4650 break;
4651 case 8:
4652 result = construct_printer_info8(p->mem_ctx, ntprinter,
4653 &r->out.info->info8, snum);
4654 break;
4655 default:
4656 result = WERR_UNKNOWN_LEVEL;
4657 break;
4660 free_a_printer(&ntprinter, 2);
4662 if (!W_ERROR_IS_OK(result)) {
4663 TALLOC_FREE(r->out.info);
4664 return result;
4667 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4668 r->out.info, r->in.level);
4669 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4671 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4674 /********************************************************************
4675 ********************************************************************/
4677 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4678 fstring *fstring_array,
4679 const char *cservername)
4681 int i, num_strings = 0;
4682 const char **array = NULL;
4684 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4686 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4687 cservername, fstring_array[i]);
4688 if (!str) {
4689 TALLOC_FREE(array);
4690 return NULL;
4694 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4695 TALLOC_FREE(array);
4696 return NULL;
4700 if (i > 0) {
4701 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4702 &array, &num_strings);
4705 return array;
4708 /********************************************************************
4709 * fill a spoolss_DriverInfo1 struct
4710 ********************************************************************/
4712 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4713 struct spoolss_DriverInfo1 *r,
4714 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4715 const char *servername,
4716 const char *architecture)
4718 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4719 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4721 return WERR_OK;
4724 /********************************************************************
4725 * fill a spoolss_DriverInfo2 struct
4726 ********************************************************************/
4728 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4729 struct spoolss_DriverInfo2 *r,
4730 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4731 const char *servername)
4734 const char *cservername = canon_servername(servername);
4736 r->version = driver->info_3->cversion;
4738 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4739 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4740 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4741 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4743 if (strlen(driver->info_3->driverpath)) {
4744 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4745 cservername, driver->info_3->driverpath);
4746 } else {
4747 r->driver_path = talloc_strdup(mem_ctx, "");
4749 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4751 if (strlen(driver->info_3->datafile)) {
4752 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4753 cservername, driver->info_3->datafile);
4754 } else {
4755 r->data_file = talloc_strdup(mem_ctx, "");
4757 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4759 if (strlen(driver->info_3->configfile)) {
4760 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4761 cservername, driver->info_3->configfile);
4762 } else {
4763 r->config_file = talloc_strdup(mem_ctx, "");
4765 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4767 return WERR_OK;
4770 /********************************************************************
4771 * fill a spoolss_DriverInfo3 struct
4772 ********************************************************************/
4774 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4775 struct spoolss_DriverInfo3 *r,
4776 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4777 const char *servername)
4779 const char *cservername = canon_servername(servername);
4781 r->version = driver->info_3->cversion;
4783 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4784 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4785 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4786 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4788 if (strlen(driver->info_3->driverpath)) {
4789 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4790 cservername, driver->info_3->driverpath);
4791 } else {
4792 r->driver_path = talloc_strdup(mem_ctx, "");
4794 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4796 if (strlen(driver->info_3->datafile)) {
4797 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4798 cservername, driver->info_3->datafile);
4799 } else {
4800 r->data_file = talloc_strdup(mem_ctx, "");
4802 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4804 if (strlen(driver->info_3->configfile)) {
4805 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4806 cservername, driver->info_3->configfile);
4807 } else {
4808 r->config_file = talloc_strdup(mem_ctx, "");
4810 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4812 if (strlen(driver->info_3->helpfile)) {
4813 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4814 cservername, driver->info_3->helpfile);
4815 } else {
4816 r->help_file = talloc_strdup(mem_ctx, "");
4818 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4820 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4821 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4822 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4823 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4825 r->dependent_files = string_array_from_driver_info(mem_ctx,
4826 driver->info_3->dependentfiles,
4827 cservername);
4828 return WERR_OK;
4831 /********************************************************************
4832 * fill a spoolss_DriverInfo4 struct
4833 ********************************************************************/
4835 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4836 struct spoolss_DriverInfo4 *r,
4837 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4838 const char *servername)
4840 const char *cservername = canon_servername(servername);
4842 r->version = driver->info_3->cversion;
4844 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4845 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4846 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4847 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4849 if (strlen(driver->info_3->driverpath)) {
4850 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4851 cservername, driver->info_3->driverpath);
4852 } else {
4853 r->driver_path = talloc_strdup(mem_ctx, "");
4855 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4857 if (strlen(driver->info_3->datafile)) {
4858 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4859 cservername, driver->info_3->datafile);
4860 } else {
4861 r->data_file = talloc_strdup(mem_ctx, "");
4863 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4865 if (strlen(driver->info_3->configfile)) {
4866 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4867 cservername, driver->info_3->configfile);
4868 } else {
4869 r->config_file = talloc_strdup(mem_ctx, "");
4871 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4873 if (strlen(driver->info_3->helpfile)) {
4874 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4875 cservername, driver->info_3->helpfile);
4876 } else {
4877 r->help_file = talloc_strdup(mem_ctx, "");
4879 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4881 r->dependent_files = string_array_from_driver_info(mem_ctx,
4882 driver->info_3->dependentfiles,
4883 cservername);
4886 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4887 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4888 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4889 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4891 r->previous_names = string_array_from_driver_info(mem_ctx,
4892 NULL,
4893 cservername);
4895 return WERR_OK;
4898 /********************************************************************
4899 * fill a spoolss_DriverInfo5 struct
4900 ********************************************************************/
4902 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4903 struct spoolss_DriverInfo5 *r,
4904 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4905 const char *servername)
4907 const char *cservername = canon_servername(servername);
4909 r->version = driver->info_3->cversion;
4911 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4912 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4913 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4914 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4916 if (strlen(driver->info_3->driverpath)) {
4917 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4918 cservername, driver->info_3->driverpath);
4919 } else {
4920 r->driver_path = talloc_strdup(mem_ctx, "");
4922 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4924 if (strlen(driver->info_3->datafile)) {
4925 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4926 cservername, driver->info_3->datafile);
4927 } else {
4928 r->data_file = talloc_strdup(mem_ctx, "");
4930 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4932 if (strlen(driver->info_3->configfile)) {
4933 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4934 cservername, driver->info_3->configfile);
4935 } else {
4936 r->config_file = talloc_strdup(mem_ctx, "");
4938 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4940 r->driver_attributes = 0;
4941 r->config_version = 0;
4942 r->driver_version = 0;
4944 return WERR_OK;
4946 /********************************************************************
4947 * fill a spoolss_DriverInfo6 struct
4948 ********************************************************************/
4950 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4951 struct spoolss_DriverInfo6 *r,
4952 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4953 const char *servername)
4955 const char *cservername = canon_servername(servername);
4957 r->version = driver->info_3->cversion;
4959 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4960 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4961 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4962 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4964 if (strlen(driver->info_3->driverpath)) {
4965 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4966 cservername, driver->info_3->driverpath);
4967 } else {
4968 r->driver_path = talloc_strdup(mem_ctx, "");
4970 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4972 if (strlen(driver->info_3->datafile)) {
4973 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4974 cservername, driver->info_3->datafile);
4975 } else {
4976 r->data_file = talloc_strdup(mem_ctx, "");
4978 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4980 if (strlen(driver->info_3->configfile)) {
4981 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4982 cservername, driver->info_3->configfile);
4983 } else {
4984 r->config_file = talloc_strdup(mem_ctx, "");
4986 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4988 if (strlen(driver->info_3->helpfile)) {
4989 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4990 cservername, driver->info_3->helpfile);
4991 } else {
4992 r->help_file = talloc_strdup(mem_ctx, "");
4994 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4996 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4997 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4998 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4999 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5001 r->dependent_files = string_array_from_driver_info(mem_ctx,
5002 driver->info_3->dependentfiles,
5003 cservername);
5004 r->previous_names = string_array_from_driver_info(mem_ctx,
5005 NULL,
5006 cservername);
5008 r->driver_date = 0;
5009 r->driver_version = 0;
5011 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5012 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5013 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5014 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5015 r->hardware_id = talloc_strdup(mem_ctx, "");
5016 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5017 r->provider = talloc_strdup(mem_ctx, "");
5018 W_ERROR_HAVE_NO_MEMORY(r->provider);
5020 return WERR_OK;
5023 /********************************************************************
5024 ********************************************************************/
5026 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5027 struct spoolss_DriverFileInfo *r,
5028 const char *cservername,
5029 const char *file_name,
5030 enum spoolss_DriverFileType file_type,
5031 uint32_t file_version)
5033 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5034 cservername, file_name);
5035 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5036 r->file_type = file_type;
5037 r->file_version = file_version;
5039 return WERR_OK;
5042 /********************************************************************
5043 ********************************************************************/
5045 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5046 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5047 const char *cservername,
5048 struct spoolss_DriverFileInfo **info_p,
5049 uint32_t *count_p)
5051 struct spoolss_DriverFileInfo *info = NULL;
5052 uint32_t count = 0;
5053 WERROR result;
5054 uint32_t i;
5056 *info_p = NULL;
5057 *count_p = 0;
5059 if (strlen(driver->info_3->driverpath)) {
5060 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5061 struct spoolss_DriverFileInfo,
5062 count + 1);
5063 W_ERROR_HAVE_NO_MEMORY(info);
5064 result = fill_spoolss_DriverFileInfo(info,
5065 &info[count],
5066 cservername,
5067 driver->info_3->driverpath,
5068 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5070 W_ERROR_NOT_OK_RETURN(result);
5071 count++;
5074 if (strlen(driver->info_3->configfile)) {
5075 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5076 struct spoolss_DriverFileInfo,
5077 count + 1);
5078 W_ERROR_HAVE_NO_MEMORY(info);
5079 result = fill_spoolss_DriverFileInfo(info,
5080 &info[count],
5081 cservername,
5082 driver->info_3->configfile,
5083 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5085 W_ERROR_NOT_OK_RETURN(result);
5086 count++;
5089 if (strlen(driver->info_3->datafile)) {
5090 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5091 struct spoolss_DriverFileInfo,
5092 count + 1);
5093 W_ERROR_HAVE_NO_MEMORY(info);
5094 result = fill_spoolss_DriverFileInfo(info,
5095 &info[count],
5096 cservername,
5097 driver->info_3->datafile,
5098 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5100 W_ERROR_NOT_OK_RETURN(result);
5101 count++;
5104 if (strlen(driver->info_3->helpfile)) {
5105 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5106 struct spoolss_DriverFileInfo,
5107 count + 1);
5108 W_ERROR_HAVE_NO_MEMORY(info);
5109 result = fill_spoolss_DriverFileInfo(info,
5110 &info[count],
5111 cservername,
5112 driver->info_3->helpfile,
5113 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5115 W_ERROR_NOT_OK_RETURN(result);
5116 count++;
5119 for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5120 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5121 struct spoolss_DriverFileInfo,
5122 count + 1);
5123 W_ERROR_HAVE_NO_MEMORY(info);
5124 result = fill_spoolss_DriverFileInfo(info,
5125 &info[count],
5126 cservername,
5127 driver->info_3->dependentfiles[i],
5128 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5130 W_ERROR_NOT_OK_RETURN(result);
5131 count++;
5134 *info_p = info;
5135 *count_p = count;
5137 return WERR_OK;
5140 /********************************************************************
5141 * fill a spoolss_DriverInfo101 sttruct
5142 ********************************************************************/
5144 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5145 struct spoolss_DriverInfo101 *r,
5146 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5147 const char *servername)
5149 const char *cservername = canon_servername(servername);
5150 WERROR result;
5152 r->version = driver->info_3->cversion;
5154 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
5155 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5156 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
5157 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5159 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5160 cservername,
5161 &r->file_info,
5162 &r->file_count);
5163 if (!W_ERROR_IS_OK(result)) {
5164 return result;
5167 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5168 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5170 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5171 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5173 r->previous_names = string_array_from_driver_info(mem_ctx,
5174 NULL,
5175 cservername);
5176 r->driver_date = 0;
5177 r->driver_version = 0;
5179 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5180 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5181 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5182 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5183 r->hardware_id = talloc_strdup(mem_ctx, "");
5184 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5185 r->provider = talloc_strdup(mem_ctx, "");
5186 W_ERROR_HAVE_NO_MEMORY(r->provider);
5188 return WERR_OK;
5191 /********************************************************************
5192 * construct_printer_driver_info_1
5193 ********************************************************************/
5195 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5196 struct spoolss_DriverInfo1 *r,
5197 int snum,
5198 const char *servername,
5199 const char *architecture,
5200 uint32_t version)
5202 NT_PRINTER_INFO_LEVEL *printer = NULL;
5203 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5204 WERROR result;
5206 ZERO_STRUCT(driver);
5208 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5209 return WERR_INVALID_PRINTER_NAME;
5211 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5212 free_a_printer(&printer, 2);
5213 return WERR_UNKNOWN_PRINTER_DRIVER;
5216 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5218 free_a_printer(&printer,2);
5220 return result;
5223 /********************************************************************
5224 * construct_printer_driver_info_2
5225 * fill a printer_info_2 struct
5226 ********************************************************************/
5228 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5229 struct spoolss_DriverInfo2 *r,
5230 int snum,
5231 const char *servername,
5232 const char *architecture,
5233 uint32_t version)
5235 NT_PRINTER_INFO_LEVEL *printer = NULL;
5236 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5237 WERROR result;
5239 ZERO_STRUCT(printer);
5240 ZERO_STRUCT(driver);
5242 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5243 return WERR_INVALID_PRINTER_NAME;
5245 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5246 free_a_printer(&printer, 2);
5247 return WERR_UNKNOWN_PRINTER_DRIVER;
5250 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5252 free_a_printer(&printer,2);
5254 return result;
5257 /********************************************************************
5258 * construct_printer_info_3
5259 * fill a printer_info_3 struct
5260 ********************************************************************/
5262 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5263 struct spoolss_DriverInfo3 *r,
5264 int snum,
5265 const char *servername,
5266 const char *architecture,
5267 uint32_t version)
5269 NT_PRINTER_INFO_LEVEL *printer = NULL;
5270 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5271 WERROR status;
5272 ZERO_STRUCT(driver);
5274 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5275 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5276 if (!W_ERROR_IS_OK(status))
5277 return WERR_INVALID_PRINTER_NAME;
5279 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5280 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5282 #if 0 /* JERRY */
5285 * I put this code in during testing. Helpful when commenting out the
5286 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5287 * as win2k always queries the driver using an infor level of 6.
5288 * I've left it in (but ifdef'd out) because I'll probably
5289 * use it in experimentation again in the future. --jerry 22/01/2002
5292 if (!W_ERROR_IS_OK(status)) {
5294 * Is this a W2k client ?
5296 if (version == 3) {
5297 /* Yes - try again with a WinNT driver. */
5298 version = 2;
5299 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5300 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5302 #endif
5304 if (!W_ERROR_IS_OK(status)) {
5305 free_a_printer(&printer,2);
5306 return WERR_UNKNOWN_PRINTER_DRIVER;
5309 #if 0 /* JERRY */
5311 #endif
5314 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5316 free_a_printer(&printer,2);
5318 return status;
5321 /********************************************************************
5322 * construct_printer_info_6
5323 * fill a printer_info_6 struct
5324 ********************************************************************/
5326 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5327 struct spoolss_DriverInfo6 *r,
5328 int snum,
5329 const char *servername,
5330 const char *architecture,
5331 uint32_t version)
5333 NT_PRINTER_INFO_LEVEL *printer = NULL;
5334 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5335 WERROR status;
5337 ZERO_STRUCT(driver);
5339 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5341 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5343 if (!W_ERROR_IS_OK(status))
5344 return WERR_INVALID_PRINTER_NAME;
5346 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5348 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5350 if (!W_ERROR_IS_OK(status))
5353 * Is this a W2k client ?
5356 if (version < 3) {
5357 free_a_printer(&printer,2);
5358 return WERR_UNKNOWN_PRINTER_DRIVER;
5361 /* Yes - try again with a WinNT driver. */
5362 version = 2;
5363 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5364 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5365 if (!W_ERROR_IS_OK(status)) {
5366 free_a_printer(&printer,2);
5367 return WERR_UNKNOWN_PRINTER_DRIVER;
5371 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5373 free_a_printer(&printer,2);
5374 free_a_printer_driver(driver, 3);
5376 return status;
5379 /********************************************************************
5380 * construct_printer_info_101
5381 * fill a printer_info_101 struct
5382 ********************************************************************/
5384 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5385 struct spoolss_DriverInfo101 *r,
5386 int snum,
5387 const char *servername,
5388 const char *architecture,
5389 uint32_t version)
5391 NT_PRINTER_INFO_LEVEL *printer = NULL;
5392 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5393 WERROR result;
5395 ZERO_STRUCT(driver);
5397 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5399 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5400 win_errstr(result)));
5402 if (!W_ERROR_IS_OK(result)) {
5403 return WERR_INVALID_PRINTER_NAME;
5406 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5407 architecture, version);
5409 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5410 win_errstr(result)));
5412 if (!W_ERROR_IS_OK(result)) {
5414 * Is this a W2k client ?
5417 if (version < 3) {
5418 free_a_printer(&printer, 2);
5419 return WERR_UNKNOWN_PRINTER_DRIVER;
5422 /* Yes - try again with a WinNT driver. */
5423 version = 2;
5424 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5425 architecture, version);
5426 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5427 win_errstr(result)));
5428 if (!W_ERROR_IS_OK(result)) {
5429 free_a_printer(&printer, 2);
5430 return WERR_UNKNOWN_PRINTER_DRIVER;
5434 result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5436 free_a_printer(&printer, 2);
5437 free_a_printer_driver(driver, 3);
5439 return result;
5442 /****************************************************************
5443 _spoolss_GetPrinterDriver2
5444 ****************************************************************/
5446 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5447 struct spoolss_GetPrinterDriver2 *r)
5449 Printer_entry *printer;
5450 WERROR result;
5452 const char *servername;
5453 int snum;
5455 /* that's an [in out] buffer */
5457 if (!r->in.buffer && (r->in.offered != 0)) {
5458 return WERR_INVALID_PARAM;
5461 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5463 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5464 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5465 return WERR_INVALID_PRINTER_NAME;
5468 *r->out.needed = 0;
5469 *r->out.server_major_version = 0;
5470 *r->out.server_minor_version = 0;
5472 servername = get_server_name(printer);
5474 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5475 return WERR_BADFID;
5478 switch (r->in.level) {
5479 case 1:
5480 result = construct_printer_driver_info_1(p->mem_ctx,
5481 &r->out.info->info1,
5482 snum,
5483 servername,
5484 r->in.architecture,
5485 r->in.client_major_version);
5486 break;
5487 case 2:
5488 result = construct_printer_driver_info_2(p->mem_ctx,
5489 &r->out.info->info2,
5490 snum,
5491 servername,
5492 r->in.architecture,
5493 r->in.client_major_version);
5494 break;
5495 case 3:
5496 result = construct_printer_driver_info_3(p->mem_ctx,
5497 &r->out.info->info3,
5498 snum,
5499 servername,
5500 r->in.architecture,
5501 r->in.client_major_version);
5502 break;
5503 case 6:
5504 result = construct_printer_driver_info_6(p->mem_ctx,
5505 &r->out.info->info6,
5506 snum,
5507 servername,
5508 r->in.architecture,
5509 r->in.client_major_version);
5510 break;
5511 case 101:
5512 result = construct_printer_driver_info_101(p->mem_ctx,
5513 &r->out.info->info101,
5514 snum,
5515 servername,
5516 r->in.architecture,
5517 r->in.client_major_version);
5518 break;
5519 default:
5520 result = WERR_UNKNOWN_LEVEL;
5521 break;
5524 if (!W_ERROR_IS_OK(result)) {
5525 TALLOC_FREE(r->out.info);
5526 return result;
5529 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5530 r->out.info, r->in.level);
5531 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5533 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5537 /****************************************************************
5538 _spoolss_StartPagePrinter
5539 ****************************************************************/
5541 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5542 struct spoolss_StartPagePrinter *r)
5544 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5546 if (!Printer) {
5547 DEBUG(3,("_spoolss_StartPagePrinter: "
5548 "Error in startpageprinter printer handle\n"));
5549 return WERR_BADFID;
5552 Printer->page_started = true;
5553 return WERR_OK;
5556 /****************************************************************
5557 _spoolss_EndPagePrinter
5558 ****************************************************************/
5560 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5561 struct spoolss_EndPagePrinter *r)
5563 int snum;
5565 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5567 if (!Printer) {
5568 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5569 OUR_HANDLE(r->in.handle)));
5570 return WERR_BADFID;
5573 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5574 return WERR_BADFID;
5576 Printer->page_started = false;
5577 print_job_endpage(snum, Printer->jobid);
5579 return WERR_OK;
5582 /****************************************************************
5583 _spoolss_StartDocPrinter
5584 ****************************************************************/
5586 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5587 struct spoolss_StartDocPrinter *r)
5589 struct spoolss_DocumentInfo1 *info_1;
5590 int snum;
5591 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5593 if (!Printer) {
5594 DEBUG(2,("_spoolss_StartDocPrinter: "
5595 "Invalid handle (%s:%u:%u)\n",
5596 OUR_HANDLE(r->in.handle)));
5597 return WERR_BADFID;
5600 if (r->in.level != 1) {
5601 return WERR_UNKNOWN_LEVEL;
5604 info_1 = r->in.info.info1;
5607 * a nice thing with NT is it doesn't listen to what you tell it.
5608 * when asked to send _only_ RAW datas, it tries to send datas
5609 * in EMF format.
5611 * So I add checks like in NT Server ...
5614 if (info_1->datatype) {
5615 if (strcmp(info_1->datatype, "RAW") != 0) {
5616 *r->out.job_id = 0;
5617 return WERR_INVALID_DATATYPE;
5621 /* get the share number of the printer */
5622 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5623 return WERR_BADFID;
5626 Printer->jobid = print_job_start(p->server_info, snum,
5627 info_1->document_name,
5628 Printer->nt_devmode);
5630 /* An error occured in print_job_start() so return an appropriate
5631 NT error code. */
5633 if (Printer->jobid == -1) {
5634 return map_werror_from_unix(errno);
5637 Printer->document_started = true;
5638 *r->out.job_id = Printer->jobid;
5640 return WERR_OK;
5643 /****************************************************************
5644 _spoolss_EndDocPrinter
5645 ****************************************************************/
5647 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5648 struct spoolss_EndDocPrinter *r)
5650 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5651 int snum;
5653 if (!Printer) {
5654 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5655 OUR_HANDLE(r->in.handle)));
5656 return WERR_BADFID;
5659 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5660 return WERR_BADFID;
5663 Printer->document_started = false;
5664 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5665 /* error codes unhandled so far ... */
5667 return WERR_OK;
5670 /****************************************************************
5671 _spoolss_WritePrinter
5672 ****************************************************************/
5674 WERROR _spoolss_WritePrinter(pipes_struct *p,
5675 struct spoolss_WritePrinter *r)
5677 uint32_t buffer_written;
5678 int snum;
5679 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5681 if (!Printer) {
5682 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5683 OUR_HANDLE(r->in.handle)));
5684 *r->out.num_written = r->in._data_size;
5685 return WERR_BADFID;
5688 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5689 return WERR_BADFID;
5691 buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5692 (const char *)r->in.data.data,
5693 (SMB_OFF_T)-1,
5694 (size_t)r->in._data_size);
5695 if (buffer_written == (uint32_t)-1) {
5696 *r->out.num_written = 0;
5697 if (errno == ENOSPC)
5698 return WERR_NO_SPOOL_SPACE;
5699 else
5700 return WERR_ACCESS_DENIED;
5703 *r->out.num_written = r->in._data_size;
5705 return WERR_OK;
5708 /********************************************************************
5709 * api_spoolss_getprinter
5710 * called from the spoolss dispatcher
5712 ********************************************************************/
5714 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5715 pipes_struct *p)
5717 int snum;
5718 WERROR errcode = WERR_BADFUNC;
5719 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5721 if (!Printer) {
5722 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5723 OUR_HANDLE(handle)));
5724 return WERR_BADFID;
5727 if (!get_printer_snum(p, handle, &snum, NULL))
5728 return WERR_BADFID;
5730 switch (command) {
5731 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5732 errcode = print_queue_pause(p->server_info, snum);
5733 break;
5734 case SPOOLSS_PRINTER_CONTROL_RESUME:
5735 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5736 errcode = print_queue_resume(p->server_info, snum);
5737 break;
5738 case SPOOLSS_PRINTER_CONTROL_PURGE:
5739 errcode = print_queue_purge(p->server_info, snum);
5740 break;
5741 default:
5742 return WERR_UNKNOWN_LEVEL;
5745 return errcode;
5749 /****************************************************************
5750 _spoolss_AbortPrinter
5751 * From MSDN: "Deletes printer's spool file if printer is configured
5752 * for spooling"
5753 ****************************************************************/
5755 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5756 struct spoolss_AbortPrinter *r)
5758 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5759 int snum;
5760 WERROR errcode = WERR_OK;
5762 if (!Printer) {
5763 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5764 OUR_HANDLE(r->in.handle)));
5765 return WERR_BADFID;
5768 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5769 return WERR_BADFID;
5771 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5773 return errcode;
5776 /********************************************************************
5777 * called by spoolss_api_setprinter
5778 * when updating a printer description
5779 ********************************************************************/
5781 static WERROR update_printer_sec(struct policy_handle *handle,
5782 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5784 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5785 WERROR result;
5786 int snum;
5788 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5790 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5791 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5792 OUR_HANDLE(handle)));
5794 result = WERR_BADFID;
5795 goto done;
5798 if (!secdesc_ctr) {
5799 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5800 result = WERR_INVALID_PARAM;
5801 goto done;
5804 /* Check the user has permissions to change the security
5805 descriptor. By experimentation with two NT machines, the user
5806 requires Full Access to the printer to change security
5807 information. */
5809 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5810 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5811 result = WERR_ACCESS_DENIED;
5812 goto done;
5815 /* NT seems to like setting the security descriptor even though
5816 nothing may have actually changed. */
5818 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5819 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5820 result = WERR_BADFID;
5821 goto done;
5824 if (DEBUGLEVEL >= 10) {
5825 SEC_ACL *the_acl;
5826 int i;
5828 the_acl = old_secdesc_ctr->sd->dacl;
5829 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5830 PRINTERNAME(snum), the_acl->num_aces));
5832 for (i = 0; i < the_acl->num_aces; i++) {
5833 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5834 &the_acl->aces[i].trustee),
5835 the_acl->aces[i].access_mask));
5838 the_acl = secdesc_ctr->sd->dacl;
5840 if (the_acl) {
5841 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5842 PRINTERNAME(snum), the_acl->num_aces));
5844 for (i = 0; i < the_acl->num_aces; i++) {
5845 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5846 &the_acl->aces[i].trustee),
5847 the_acl->aces[i].access_mask));
5849 } else {
5850 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5854 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5855 if (!new_secdesc_ctr) {
5856 result = WERR_NOMEM;
5857 goto done;
5860 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5861 result = WERR_OK;
5862 goto done;
5865 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5867 done:
5869 return result;
5872 /********************************************************************
5873 Canonicalize printer info from a client
5875 ATTN: It does not matter what we set the servername to hear
5876 since we do the necessary work in get_a_printer() to set it to
5877 the correct value based on what the client sent in the
5878 _spoolss_open_printer_ex().
5879 ********************************************************************/
5881 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5883 fstring printername;
5884 const char *p;
5886 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5887 "portname=%s drivername=%s comment=%s location=%s\n",
5888 info->servername, info->printername, info->sharename,
5889 info->portname, info->drivername, info->comment, info->location));
5891 /* we force some elements to "correct" values */
5892 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5893 fstrcpy(info->sharename, lp_servicename(snum));
5895 /* check to see if we allow printername != sharename */
5897 if ( lp_force_printername(snum) ) {
5898 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5899 global_myname(), info->sharename );
5900 } else {
5902 /* make sure printername is in \\server\printername format */
5904 fstrcpy( printername, info->printername );
5905 p = printername;
5906 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5907 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5908 p++;
5911 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5912 global_myname(), p );
5915 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5916 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5920 return true;
5923 /****************************************************************************
5924 ****************************************************************************/
5926 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5928 char *cmd = lp_addport_cmd();
5929 char *command = NULL;
5930 int ret;
5931 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5932 bool is_print_op = false;
5934 if ( !*cmd ) {
5935 return WERR_ACCESS_DENIED;
5938 command = talloc_asprintf(ctx,
5939 "%s \"%s\" \"%s\"", cmd, portname, uri );
5940 if (!command) {
5941 return WERR_NOMEM;
5944 if ( token )
5945 is_print_op = user_has_privileges( token, &se_printop );
5947 DEBUG(10,("Running [%s]\n", command));
5949 /********* BEGIN SePrintOperatorPrivilege **********/
5951 if ( is_print_op )
5952 become_root();
5954 ret = smbrun(command, NULL);
5956 if ( is_print_op )
5957 unbecome_root();
5959 /********* END SePrintOperatorPrivilege **********/
5961 DEBUGADD(10,("returned [%d]\n", ret));
5963 TALLOC_FREE(command);
5965 if ( ret != 0 ) {
5966 return WERR_ACCESS_DENIED;
5969 return WERR_OK;
5972 /****************************************************************************
5973 ****************************************************************************/
5975 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5977 char *cmd = lp_addprinter_cmd();
5978 char **qlines;
5979 char *command = NULL;
5980 int numlines;
5981 int ret;
5982 int fd;
5983 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5984 bool is_print_op = false;
5985 char *remote_machine = talloc_strdup(ctx, "%m");
5987 if (!remote_machine) {
5988 return false;
5990 remote_machine = talloc_sub_basic(ctx,
5991 current_user_info.smb_name,
5992 current_user_info.domain,
5993 remote_machine);
5994 if (!remote_machine) {
5995 return false;
5998 command = talloc_asprintf(ctx,
5999 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6000 cmd, printer->info_2->printername, printer->info_2->sharename,
6001 printer->info_2->portname, printer->info_2->drivername,
6002 printer->info_2->location, printer->info_2->comment, remote_machine);
6003 if (!command) {
6004 return false;
6007 if ( token )
6008 is_print_op = user_has_privileges( token, &se_printop );
6010 DEBUG(10,("Running [%s]\n", command));
6012 /********* BEGIN SePrintOperatorPrivilege **********/
6014 if ( is_print_op )
6015 become_root();
6017 if ( (ret = smbrun(command, &fd)) == 0 ) {
6018 /* Tell everyone we updated smb.conf. */
6019 message_send_all(smbd_messaging_context(),
6020 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6023 if ( is_print_op )
6024 unbecome_root();
6026 /********* END SePrintOperatorPrivilege **********/
6028 DEBUGADD(10,("returned [%d]\n", ret));
6030 TALLOC_FREE(command);
6031 TALLOC_FREE(remote_machine);
6033 if ( ret != 0 ) {
6034 if (fd != -1)
6035 close(fd);
6036 return false;
6039 /* reload our services immediately */
6040 become_root();
6041 reload_services(false);
6042 unbecome_root();
6044 numlines = 0;
6045 /* Get lines and convert them back to dos-codepage */
6046 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6047 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6048 close(fd);
6050 /* Set the portname to what the script says the portname should be. */
6051 /* but don't require anything to be return from the script exit a good error code */
6053 if (numlines) {
6054 /* Set the portname to what the script says the portname should be. */
6055 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6056 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6059 TALLOC_FREE(qlines);
6060 return true;
6064 /********************************************************************
6065 * Called by spoolss_api_setprinter
6066 * when updating a printer description.
6067 ********************************************************************/
6069 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
6070 struct spoolss_SetPrinterInfoCtr *info_ctr,
6071 struct spoolss_DeviceMode *devmode)
6073 int snum;
6074 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6075 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6076 WERROR result;
6077 DATA_BLOB buffer;
6078 fstring asc_buffer;
6080 DEBUG(8,("update_printer\n"));
6082 result = WERR_OK;
6084 if (!Printer) {
6085 result = WERR_BADFID;
6086 goto done;
6089 if (!get_printer_snum(p, handle, &snum, NULL)) {
6090 result = WERR_BADFID;
6091 goto done;
6094 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6095 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6096 result = WERR_BADFID;
6097 goto done;
6100 DEBUGADD(8,("Converting info_2 struct\n"));
6103 * convert_printer_info converts the incoming
6104 * info from the client and overwrites the info
6105 * just read from the tdb in the pointer 'printer'.
6108 if (!convert_printer_info(info_ctr, printer)) {
6109 result = WERR_NOMEM;
6110 goto done;
6113 if (devmode) {
6114 /* we have a valid devmode
6115 convert it and link it*/
6117 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6118 if (!convert_devicemode(printer->info_2->printername, devmode,
6119 &printer->info_2->devmode)) {
6120 result = WERR_NOMEM;
6121 goto done;
6125 /* Do sanity check on the requested changes for Samba */
6127 if (!check_printer_ok(printer->info_2, snum)) {
6128 result = WERR_INVALID_PARAM;
6129 goto done;
6132 /* FIXME!!! If the driver has changed we really should verify that
6133 it is installed before doing much else --jerry */
6135 /* Check calling user has permission to update printer description */
6137 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6138 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6139 result = WERR_ACCESS_DENIED;
6140 goto done;
6143 /* Call addprinter hook */
6144 /* Check changes to see if this is really needed */
6146 if ( *lp_addprinter_cmd()
6147 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6148 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6149 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6150 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6152 /* add_printer_hook() will call reload_services() */
6154 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6155 printer) ) {
6156 result = WERR_ACCESS_DENIED;
6157 goto done;
6162 * When a *new* driver is bound to a printer, the drivername is used to
6163 * lookup previously saved driver initialization info, which is then
6164 * bound to the printer, simulating what happens in the Windows arch.
6166 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6168 if (!set_driver_init(printer, 2))
6170 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6171 printer->info_2->drivername));
6174 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6175 printer->info_2->drivername));
6177 notify_printer_driver(snum, printer->info_2->drivername);
6181 * flag which changes actually occured. This is a small subset of
6182 * all the possible changes. We also have to update things in the
6183 * DsSpooler key.
6186 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6187 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
6188 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6189 REG_SZ, buffer.data, buffer.length);
6191 notify_printer_comment(snum, printer->info_2->comment);
6194 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6195 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
6196 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6197 REG_SZ, buffer.data, buffer.length);
6199 notify_printer_sharename(snum, printer->info_2->sharename);
6202 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6203 char *pname;
6205 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6206 pname++;
6207 else
6208 pname = printer->info_2->printername;
6211 push_reg_sz(talloc_tos(), &buffer, pname);
6212 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6213 REG_SZ, buffer.data, buffer.length);
6215 notify_printer_printername( snum, pname );
6218 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6219 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
6220 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6221 REG_SZ, buffer.data, buffer.length);
6223 notify_printer_port(snum, printer->info_2->portname);
6226 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6227 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
6228 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6229 REG_SZ, buffer.data, buffer.length);
6231 notify_printer_location(snum, printer->info_2->location);
6234 /* here we need to update some more DsSpooler keys */
6235 /* uNCName, serverName, shortServerName */
6237 push_reg_sz(talloc_tos(), &buffer, global_myname());
6238 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6239 REG_SZ, buffer.data, buffer.length);
6240 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6241 REG_SZ, buffer.data, buffer.length);
6243 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6244 global_myname(), printer->info_2->sharename );
6245 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
6246 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6247 REG_SZ, buffer.data, buffer.length);
6249 /* Update printer info */
6250 result = mod_a_printer(printer, 2);
6252 done:
6253 free_a_printer(&printer, 2);
6254 free_a_printer(&old_printer, 2);
6257 return result;
6260 /****************************************************************************
6261 ****************************************************************************/
6262 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6263 struct policy_handle *handle,
6264 struct spoolss_SetPrinterInfo7 *info7)
6266 #ifdef HAVE_ADS
6267 int snum;
6268 Printer_entry *Printer;
6270 if ( lp_security() != SEC_ADS ) {
6271 return WERR_UNKNOWN_LEVEL;
6274 Printer = find_printer_index_by_hnd(p, handle);
6276 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6278 if (!Printer)
6279 return WERR_BADFID;
6281 if (!get_printer_snum(p, handle, &snum, NULL))
6282 return WERR_BADFID;
6284 nt_printer_publish(Printer, snum, info7->action);
6286 return WERR_OK;
6287 #else
6288 return WERR_UNKNOWN_LEVEL;
6289 #endif
6292 /****************************************************************
6293 _spoolss_SetPrinter
6294 ****************************************************************/
6296 WERROR _spoolss_SetPrinter(pipes_struct *p,
6297 struct spoolss_SetPrinter *r)
6299 WERROR result;
6301 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6303 if (!Printer) {
6304 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6305 OUR_HANDLE(r->in.handle)));
6306 return WERR_BADFID;
6309 /* check the level */
6310 switch (r->in.info_ctr->level) {
6311 case 0:
6312 return control_printer(r->in.handle, r->in.command, p);
6313 case 2:
6314 result = update_printer(p, r->in.handle,
6315 r->in.info_ctr,
6316 r->in.devmode_ctr->devmode);
6317 if (!W_ERROR_IS_OK(result))
6318 return result;
6319 if (r->in.secdesc_ctr->sd)
6320 result = update_printer_sec(r->in.handle, p,
6321 r->in.secdesc_ctr);
6322 return result;
6323 case 3:
6324 return update_printer_sec(r->in.handle, p,
6325 r->in.secdesc_ctr);
6326 case 7:
6327 return publish_or_unpublish_printer(p, r->in.handle,
6328 r->in.info_ctr->info.info7);
6329 default:
6330 return WERR_UNKNOWN_LEVEL;
6334 /****************************************************************
6335 _spoolss_FindClosePrinterNotify
6336 ****************************************************************/
6338 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6339 struct spoolss_FindClosePrinterNotify *r)
6341 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6343 if (!Printer) {
6344 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6345 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6346 return WERR_BADFID;
6349 if (Printer->notify.client_connected == true) {
6350 int snum = -1;
6352 if ( Printer->printer_type == SPLHND_SERVER)
6353 snum = -1;
6354 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6355 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6356 return WERR_BADFID;
6358 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6361 Printer->notify.flags=0;
6362 Printer->notify.options=0;
6363 Printer->notify.localmachine[0]='\0';
6364 Printer->notify.printerlocal=0;
6365 TALLOC_FREE(Printer->notify.option);
6366 Printer->notify.client_connected = false;
6368 return WERR_OK;
6371 /****************************************************************
6372 _spoolss_AddJob
6373 ****************************************************************/
6375 WERROR _spoolss_AddJob(pipes_struct *p,
6376 struct spoolss_AddJob *r)
6378 if (!r->in.buffer && (r->in.offered != 0)) {
6379 return WERR_INVALID_PARAM;
6382 /* this is what a NT server returns for AddJob. AddJob must fail on
6383 * non-local printers */
6385 if (r->in.level != 1) {
6386 return WERR_UNKNOWN_LEVEL;
6389 return WERR_INVALID_PARAM;
6392 /****************************************************************************
6393 fill_job_info1
6394 ****************************************************************************/
6396 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6397 struct spoolss_JobInfo1 *r,
6398 const print_queue_struct *queue,
6399 int position, int snum,
6400 const NT_PRINTER_INFO_LEVEL *ntprinter)
6402 struct tm *t;
6404 t = gmtime(&queue->time);
6406 r->job_id = queue->job;
6408 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6409 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6410 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6411 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6412 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6413 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6414 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6415 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6416 r->data_type = talloc_strdup(mem_ctx, "RAW");
6417 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6418 r->text_status = talloc_strdup(mem_ctx, "");
6419 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6421 r->status = nt_printj_status(queue->status);
6422 r->priority = queue->priority;
6423 r->position = position;
6424 r->total_pages = queue->page_count;
6425 r->pages_printed = 0; /* ??? */
6427 init_systemtime(&r->submitted, t);
6429 return WERR_OK;
6432 /****************************************************************************
6433 fill_job_info2
6434 ****************************************************************************/
6436 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6437 struct spoolss_JobInfo2 *r,
6438 const print_queue_struct *queue,
6439 int position, int snum,
6440 const NT_PRINTER_INFO_LEVEL *ntprinter,
6441 struct spoolss_DeviceMode *devmode)
6443 struct tm *t;
6445 t = gmtime(&queue->time);
6447 r->job_id = queue->job;
6449 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6450 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6451 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6452 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6453 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6454 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6455 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6456 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6457 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6458 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6459 r->data_type = talloc_strdup(mem_ctx, "RAW");
6460 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6461 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6462 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6463 r->parameters = talloc_strdup(mem_ctx, "");
6464 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6465 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6466 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6468 r->devmode = devmode;
6470 r->text_status = talloc_strdup(mem_ctx, "");
6471 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6473 r->secdesc = NULL;
6475 r->status = nt_printj_status(queue->status);
6476 r->priority = queue->priority;
6477 r->position = position;
6478 r->start_time = 0;
6479 r->until_time = 0;
6480 r->total_pages = queue->page_count;
6481 r->size = queue->size;
6482 init_systemtime(&r->submitted, t);
6483 r->time = 0;
6484 r->pages_printed = 0; /* ??? */
6486 return WERR_OK;
6489 /****************************************************************************
6490 Enumjobs at level 1.
6491 ****************************************************************************/
6493 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6494 const print_queue_struct *queue,
6495 uint32_t num_queues, int snum,
6496 const NT_PRINTER_INFO_LEVEL *ntprinter,
6497 union spoolss_JobInfo **info_p,
6498 uint32_t *count)
6500 union spoolss_JobInfo *info;
6501 int i;
6502 WERROR result = WERR_OK;
6504 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6505 W_ERROR_HAVE_NO_MEMORY(info);
6507 *count = num_queues;
6509 for (i=0; i<*count; i++) {
6510 result = fill_job_info1(info,
6511 &info[i].info1,
6512 &queue[i],
6514 snum,
6515 ntprinter);
6516 if (!W_ERROR_IS_OK(result)) {
6517 goto out;
6521 out:
6522 if (!W_ERROR_IS_OK(result)) {
6523 TALLOC_FREE(info);
6524 *count = 0;
6525 return result;
6528 *info_p = info;
6530 return WERR_OK;
6533 /****************************************************************************
6534 Enumjobs at level 2.
6535 ****************************************************************************/
6537 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6538 const print_queue_struct *queue,
6539 uint32_t num_queues, int snum,
6540 const NT_PRINTER_INFO_LEVEL *ntprinter,
6541 union spoolss_JobInfo **info_p,
6542 uint32_t *count)
6544 union spoolss_JobInfo *info;
6545 int i;
6546 WERROR result = WERR_OK;
6548 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6549 W_ERROR_HAVE_NO_MEMORY(info);
6551 *count = num_queues;
6553 for (i=0; i<*count; i++) {
6555 struct spoolss_DeviceMode *devmode;
6557 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6558 if (!devmode) {
6559 result = WERR_NOMEM;
6560 goto out;
6563 result = fill_job_info2(info,
6564 &info[i].info2,
6565 &queue[i],
6567 snum,
6568 ntprinter,
6569 devmode);
6570 if (!W_ERROR_IS_OK(result)) {
6571 goto out;
6575 out:
6576 if (!W_ERROR_IS_OK(result)) {
6577 TALLOC_FREE(info);
6578 *count = 0;
6579 return result;
6582 *info_p = info;
6584 return WERR_OK;
6587 /****************************************************************
6588 _spoolss_EnumJobs
6589 ****************************************************************/
6591 WERROR _spoolss_EnumJobs(pipes_struct *p,
6592 struct spoolss_EnumJobs *r)
6594 WERROR result;
6595 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6596 int snum;
6597 print_status_struct prt_status;
6598 print_queue_struct *queue = NULL;
6599 uint32_t count;
6601 /* that's an [in out] buffer */
6603 if (!r->in.buffer && (r->in.offered != 0)) {
6604 return WERR_INVALID_PARAM;
6607 DEBUG(4,("_spoolss_EnumJobs\n"));
6609 *r->out.needed = 0;
6610 *r->out.count = 0;
6611 *r->out.info = NULL;
6613 /* lookup the printer snum and tdb entry */
6615 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6616 return WERR_BADFID;
6619 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6620 if (!W_ERROR_IS_OK(result)) {
6621 return result;
6624 count = print_queue_status(snum, &queue, &prt_status);
6625 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6626 count, prt_status.status, prt_status.message));
6628 if (count == 0) {
6629 SAFE_FREE(queue);
6630 free_a_printer(&ntprinter, 2);
6631 return WERR_OK;
6634 switch (r->in.level) {
6635 case 1:
6636 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6637 ntprinter, r->out.info, r->out.count);
6638 break;
6639 case 2:
6640 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6641 ntprinter, r->out.info, r->out.count);
6642 break;
6643 default:
6644 result = WERR_UNKNOWN_LEVEL;
6645 break;
6648 SAFE_FREE(queue);
6649 free_a_printer(&ntprinter, 2);
6651 if (!W_ERROR_IS_OK(result)) {
6652 return result;
6655 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6656 spoolss_EnumJobs, NULL,
6657 *r->out.info, r->in.level,
6658 *r->out.count);
6659 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6660 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6662 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6665 /****************************************************************
6666 _spoolss_ScheduleJob
6667 ****************************************************************/
6669 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6670 struct spoolss_ScheduleJob *r)
6672 return WERR_OK;
6675 /****************************************************************
6676 _spoolss_SetJob
6677 ****************************************************************/
6679 WERROR _spoolss_SetJob(pipes_struct *p,
6680 struct spoolss_SetJob *r)
6682 int snum;
6683 WERROR errcode = WERR_BADFUNC;
6685 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6686 return WERR_BADFID;
6689 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6690 return WERR_INVALID_PRINTER_NAME;
6693 switch (r->in.command) {
6694 case SPOOLSS_JOB_CONTROL_CANCEL:
6695 case SPOOLSS_JOB_CONTROL_DELETE:
6696 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6697 errcode = WERR_OK;
6699 break;
6700 case SPOOLSS_JOB_CONTROL_PAUSE:
6701 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6702 errcode = WERR_OK;
6704 break;
6705 case SPOOLSS_JOB_CONTROL_RESTART:
6706 case SPOOLSS_JOB_CONTROL_RESUME:
6707 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6708 errcode = WERR_OK;
6710 break;
6711 default:
6712 return WERR_UNKNOWN_LEVEL;
6715 return errcode;
6718 /****************************************************************************
6719 Enumerates all printer drivers by level and architecture.
6720 ****************************************************************************/
6722 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6723 const char *servername,
6724 const char *architecture,
6725 uint32_t level,
6726 union spoolss_DriverInfo **info_p,
6727 uint32_t *count_p)
6729 int i;
6730 int ndrivers;
6731 uint32_t version;
6732 fstring *list = NULL;
6733 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6734 union spoolss_DriverInfo *info = NULL;
6735 uint32_t count = 0;
6736 WERROR result = WERR_OK;
6738 *count_p = 0;
6739 *info_p = NULL;
6741 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6742 list = NULL;
6743 ndrivers = get_ntdrivers(&list, architecture, version);
6744 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6745 ndrivers, architecture, version));
6747 if (ndrivers == -1) {
6748 result = WERR_NOMEM;
6749 goto out;
6752 if (ndrivers != 0) {
6753 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6754 union spoolss_DriverInfo,
6755 count + ndrivers);
6756 if (!info) {
6757 DEBUG(0,("enumprinterdrivers_level1: "
6758 "failed to enlarge driver info buffer!\n"));
6759 result = WERR_NOMEM;
6760 goto out;
6764 for (i=0; i<ndrivers; i++) {
6765 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6766 ZERO_STRUCT(driver);
6767 result = get_a_printer_driver(&driver, 3, list[i],
6768 architecture, version);
6769 if (!W_ERROR_IS_OK(result)) {
6770 goto out;
6773 switch (level) {
6774 case 1:
6775 result = fill_printer_driver_info1(info, &info[count+i].info1,
6776 &driver, servername,
6777 architecture);
6778 break;
6779 case 2:
6780 result = fill_printer_driver_info2(info, &info[count+i].info2,
6781 &driver, servername);
6782 break;
6783 case 3:
6784 result = fill_printer_driver_info3(info, &info[count+i].info3,
6785 &driver, servername);
6786 break;
6787 case 4:
6788 result = fill_printer_driver_info4(info, &info[count+i].info4,
6789 &driver, servername);
6790 break;
6791 case 5:
6792 result = fill_printer_driver_info5(info, &info[count+i].info5,
6793 &driver, servername);
6794 break;
6795 case 6:
6796 result = fill_printer_driver_info6(info, &info[count+i].info6,
6797 &driver, servername);
6798 break;
6799 default:
6800 result = WERR_UNKNOWN_LEVEL;
6801 break;
6804 if (!W_ERROR_IS_OK(result)) {
6805 free_a_printer_driver(driver, 3);
6806 goto out;
6808 free_a_printer_driver(driver, 3);
6811 count += ndrivers;
6812 SAFE_FREE(list);
6815 out:
6816 SAFE_FREE(list);
6818 if (!W_ERROR_IS_OK(result)) {
6819 TALLOC_FREE(info);
6820 return result;
6823 *info_p = info;
6824 *count_p = count;
6826 return WERR_OK;
6829 /****************************************************************************
6830 Enumerates all printer drivers by level.
6831 ****************************************************************************/
6833 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6834 const char *servername,
6835 const char *architecture,
6836 uint32_t level,
6837 union spoolss_DriverInfo **info_p,
6838 uint32_t *count_p)
6840 uint32_t a,i;
6841 WERROR result = WERR_OK;
6843 if (strequal(architecture, "all")) {
6845 for (a=0; archi_table[a].long_archi != NULL; a++) {
6847 union spoolss_DriverInfo *info = NULL;
6848 uint32_t count = 0;
6850 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6851 servername,
6852 archi_table[a].long_archi,
6853 level,
6854 &info,
6855 &count);
6856 if (!W_ERROR_IS_OK(result)) {
6857 continue;
6860 for (i=0; i < count; i++) {
6861 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6862 info[i], info_p, count_p);
6866 return result;
6869 return enumprinterdrivers_level_by_architecture(mem_ctx,
6870 servername,
6871 architecture,
6872 level,
6873 info_p,
6874 count_p);
6877 /****************************************************************************
6878 Enumerates all printer drivers at level 1.
6879 ****************************************************************************/
6881 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6882 const char *servername,
6883 const char *architecture,
6884 union spoolss_DriverInfo **info_p,
6885 uint32_t *count)
6887 return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6888 info_p, count);
6891 /****************************************************************************
6892 Enumerates all printer drivers at level 2.
6893 ****************************************************************************/
6895 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6896 const char *servername,
6897 const char *architecture,
6898 union spoolss_DriverInfo **info_p,
6899 uint32_t *count)
6901 return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6902 info_p, count);
6905 /****************************************************************************
6906 Enumerates all printer drivers at level 3.
6907 ****************************************************************************/
6909 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6910 const char *servername,
6911 const char *architecture,
6912 union spoolss_DriverInfo **info_p,
6913 uint32_t *count)
6915 return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6916 info_p, count);
6919 /****************************************************************************
6920 Enumerates all printer drivers at level 4.
6921 ****************************************************************************/
6923 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6924 const char *servername,
6925 const char *architecture,
6926 union spoolss_DriverInfo **info_p,
6927 uint32_t *count)
6929 return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6930 info_p, count);
6933 /****************************************************************************
6934 Enumerates all printer drivers at level 5.
6935 ****************************************************************************/
6937 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6938 const char *servername,
6939 const char *architecture,
6940 union spoolss_DriverInfo **info_p,
6941 uint32_t *count)
6943 return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6944 info_p, count);
6947 /****************************************************************************
6948 Enumerates all printer drivers at level 6.
6949 ****************************************************************************/
6951 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6952 const char *servername,
6953 const char *architecture,
6954 union spoolss_DriverInfo **info_p,
6955 uint32_t *count)
6957 return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6958 info_p, count);
6962 /****************************************************************
6963 _spoolss_EnumPrinterDrivers
6964 ****************************************************************/
6966 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6967 struct spoolss_EnumPrinterDrivers *r)
6969 const char *cservername;
6970 WERROR result;
6972 /* that's an [in out] buffer */
6974 if (!r->in.buffer && (r->in.offered != 0)) {
6975 return WERR_INVALID_PARAM;
6978 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6980 *r->out.needed = 0;
6981 *r->out.count = 0;
6982 *r->out.info = NULL;
6984 cservername = canon_servername(r->in.server);
6986 if (!is_myname_or_ipaddr(cservername)) {
6987 return WERR_UNKNOWN_PRINTER_DRIVER;
6990 switch (r->in.level) {
6991 case 1:
6992 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6993 r->in.environment,
6994 r->out.info, r->out.count);
6995 break;
6996 case 2:
6997 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6998 r->in.environment,
6999 r->out.info, r->out.count);
7000 break;
7001 case 3:
7002 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
7003 r->in.environment,
7004 r->out.info, r->out.count);
7005 break;
7006 case 4:
7007 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
7008 r->in.environment,
7009 r->out.info, r->out.count);
7010 break;
7011 case 5:
7012 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
7013 r->in.environment,
7014 r->out.info, r->out.count);
7015 break;
7016 case 6:
7017 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
7018 r->in.environment,
7019 r->out.info, r->out.count);
7020 break;
7021 default:
7022 return WERR_UNKNOWN_LEVEL;
7025 if (!W_ERROR_IS_OK(result)) {
7026 return result;
7029 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7030 spoolss_EnumPrinterDrivers, NULL,
7031 *r->out.info, r->in.level,
7032 *r->out.count);
7033 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7034 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7036 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7039 /****************************************************************************
7040 ****************************************************************************/
7042 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7043 struct spoolss_FormInfo1 *r,
7044 const nt_forms_struct *form)
7046 r->form_name = talloc_strdup(mem_ctx, form->name);
7047 W_ERROR_HAVE_NO_MEMORY(r->form_name);
7049 r->flags = form->flag;
7050 r->size.width = form->width;
7051 r->size.height = form->length;
7052 r->area.left = form->left;
7053 r->area.top = form->top;
7054 r->area.right = form->right;
7055 r->area.bottom = form->bottom;
7057 return WERR_OK;
7060 /****************************************************************
7061 spoolss_enumforms_level1
7062 ****************************************************************/
7064 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7065 const nt_forms_struct *builtin_forms,
7066 uint32_t num_builtin_forms,
7067 const nt_forms_struct *user_forms,
7068 uint32_t num_user_forms,
7069 union spoolss_FormInfo **info_p,
7070 uint32_t *count)
7072 union spoolss_FormInfo *info;
7073 WERROR result = WERR_OK;
7074 int i;
7076 *count = num_builtin_forms + num_user_forms;
7078 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7079 W_ERROR_HAVE_NO_MEMORY(info);
7081 /* construct the list of form structures */
7082 for (i=0; i<num_builtin_forms; i++) {
7083 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
7084 result = fill_form_info_1(info, &info[i].info1,
7085 &builtin_forms[i]);
7086 if (!W_ERROR_IS_OK(result)) {
7087 goto out;
7091 for (i=0; i<num_user_forms; i++) {
7092 DEBUGADD(6,("Filling user form number [%d]\n",i));
7093 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
7094 &user_forms[i]);
7095 if (!W_ERROR_IS_OK(result)) {
7096 goto out;
7100 out:
7101 if (!W_ERROR_IS_OK(result)) {
7102 TALLOC_FREE(info);
7103 *count = 0;
7104 return result;
7107 *info_p = info;
7109 return WERR_OK;
7112 /****************************************************************
7113 _spoolss_EnumForms
7114 ****************************************************************/
7116 WERROR _spoolss_EnumForms(pipes_struct *p,
7117 struct spoolss_EnumForms *r)
7119 WERROR result;
7120 nt_forms_struct *user_forms = NULL;
7121 nt_forms_struct *builtin_forms = NULL;
7122 uint32_t num_user_forms;
7123 uint32_t num_builtin_forms;
7125 *r->out.count = 0;
7126 *r->out.needed = 0;
7127 *r->out.info = NULL;
7129 /* that's an [in out] buffer */
7131 if (!r->in.buffer && (r->in.offered != 0) ) {
7132 return WERR_INVALID_PARAM;
7135 DEBUG(4,("_spoolss_EnumForms\n"));
7136 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7137 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7139 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7140 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7141 num_user_forms = get_ntforms(&user_forms);
7142 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7144 if (num_user_forms + num_builtin_forms == 0) {
7145 SAFE_FREE(builtin_forms);
7146 SAFE_FREE(user_forms);
7147 return WERR_NO_MORE_ITEMS;
7150 switch (r->in.level) {
7151 case 1:
7152 result = spoolss_enumforms_level1(p->mem_ctx,
7153 builtin_forms,
7154 num_builtin_forms,
7155 user_forms,
7156 num_user_forms,
7157 r->out.info,
7158 r->out.count);
7159 break;
7160 default:
7161 result = WERR_UNKNOWN_LEVEL;
7162 break;
7165 SAFE_FREE(user_forms);
7166 SAFE_FREE(builtin_forms);
7168 if (!W_ERROR_IS_OK(result)) {
7169 return result;
7172 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7173 spoolss_EnumForms, NULL,
7174 *r->out.info, r->in.level,
7175 *r->out.count);
7176 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7177 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7179 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7182 /****************************************************************
7183 ****************************************************************/
7185 static WERROR find_form_byname(const char *name,
7186 nt_forms_struct *form)
7188 nt_forms_struct *list = NULL;
7189 int num_forms = 0, i = 0;
7191 if (get_a_builtin_ntform_by_string(name, form)) {
7192 return WERR_OK;
7195 num_forms = get_ntforms(&list);
7196 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7198 if (num_forms == 0) {
7199 return WERR_BADFID;
7202 /* Check if the requested name is in the list of form structures */
7203 for (i = 0; i < num_forms; i++) {
7205 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7207 if (strequal(name, list[i].name)) {
7208 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7209 *form = list[i];
7210 SAFE_FREE(list);
7211 return WERR_OK;
7215 SAFE_FREE(list);
7217 return WERR_BADFID;
7220 /****************************************************************
7221 _spoolss_GetForm
7222 ****************************************************************/
7224 WERROR _spoolss_GetForm(pipes_struct *p,
7225 struct spoolss_GetForm *r)
7227 WERROR result;
7228 nt_forms_struct form;
7230 /* that's an [in out] buffer */
7232 if (!r->in.buffer && (r->in.offered != 0)) {
7233 return WERR_INVALID_PARAM;
7236 DEBUG(4,("_spoolss_GetForm\n"));
7237 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7238 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7240 result = find_form_byname(r->in.form_name, &form);
7241 if (!W_ERROR_IS_OK(result)) {
7242 TALLOC_FREE(r->out.info);
7243 return result;
7246 switch (r->in.level) {
7247 case 1:
7248 result = fill_form_info_1(p->mem_ctx,
7249 &r->out.info->info1,
7250 &form);
7251 break;
7253 default:
7254 result = WERR_UNKNOWN_LEVEL;
7255 break;
7258 if (!W_ERROR_IS_OK(result)) {
7259 TALLOC_FREE(r->out.info);
7260 return result;
7263 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7264 r->out.info, r->in.level);
7265 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7267 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7270 /****************************************************************************
7271 ****************************************************************************/
7273 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7274 struct spoolss_PortInfo1 *r,
7275 const char *name)
7277 r->port_name = talloc_strdup(mem_ctx, name);
7278 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7280 return WERR_OK;
7283 /****************************************************************************
7284 TODO: This probably needs distinguish between TCP/IP and Local ports
7285 somehow.
7286 ****************************************************************************/
7288 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7289 struct spoolss_PortInfo2 *r,
7290 const char *name)
7292 r->port_name = talloc_strdup(mem_ctx, name);
7293 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7295 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7296 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7298 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7299 W_ERROR_HAVE_NO_MEMORY(r->description);
7301 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7302 r->reserved = 0;
7304 return WERR_OK;
7308 /****************************************************************************
7309 wrapper around the enumer ports command
7310 ****************************************************************************/
7312 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7314 char *cmd = lp_enumports_cmd();
7315 char **qlines = NULL;
7316 char *command = NULL;
7317 int numlines;
7318 int ret;
7319 int fd;
7321 *count = 0;
7322 *lines = NULL;
7324 /* if no hook then just fill in the default port */
7326 if ( !*cmd ) {
7327 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7328 return WERR_NOMEM;
7330 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7331 TALLOC_FREE(qlines);
7332 return WERR_NOMEM;
7334 qlines[1] = NULL;
7335 numlines = 1;
7337 else {
7338 /* we have a valid enumport command */
7340 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7341 if (!command) {
7342 return WERR_NOMEM;
7345 DEBUG(10,("Running [%s]\n", command));
7346 ret = smbrun(command, &fd);
7347 DEBUG(10,("Returned [%d]\n", ret));
7348 TALLOC_FREE(command);
7349 if (ret != 0) {
7350 if (fd != -1) {
7351 close(fd);
7353 return WERR_ACCESS_DENIED;
7356 numlines = 0;
7357 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7358 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7359 close(fd);
7362 *count = numlines;
7363 *lines = qlines;
7365 return WERR_OK;
7368 /****************************************************************************
7369 enumports level 1.
7370 ****************************************************************************/
7372 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7373 union spoolss_PortInfo **info_p,
7374 uint32_t *count)
7376 union spoolss_PortInfo *info = NULL;
7377 int i=0;
7378 WERROR result = WERR_OK;
7379 char **qlines = NULL;
7380 int numlines = 0;
7382 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7383 if (!W_ERROR_IS_OK(result)) {
7384 goto out;
7387 if (numlines) {
7388 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7389 if (!info) {
7390 DEBUG(10,("Returning WERR_NOMEM\n"));
7391 result = WERR_NOMEM;
7392 goto out;
7395 for (i=0; i<numlines; i++) {
7396 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7397 result = fill_port_1(info, &info[i].info1, qlines[i]);
7398 if (!W_ERROR_IS_OK(result)) {
7399 goto out;
7403 TALLOC_FREE(qlines);
7405 out:
7406 if (!W_ERROR_IS_OK(result)) {
7407 TALLOC_FREE(info);
7408 TALLOC_FREE(qlines);
7409 *count = 0;
7410 *info_p = NULL;
7411 return result;
7414 *info_p = info;
7415 *count = numlines;
7417 return WERR_OK;
7420 /****************************************************************************
7421 enumports level 2.
7422 ****************************************************************************/
7424 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7425 union spoolss_PortInfo **info_p,
7426 uint32_t *count)
7428 union spoolss_PortInfo *info = NULL;
7429 int i=0;
7430 WERROR result = WERR_OK;
7431 char **qlines = NULL;
7432 int numlines = 0;
7434 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7435 if (!W_ERROR_IS_OK(result)) {
7436 goto out;
7439 if (numlines) {
7440 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7441 if (!info) {
7442 DEBUG(10,("Returning WERR_NOMEM\n"));
7443 result = WERR_NOMEM;
7444 goto out;
7447 for (i=0; i<numlines; i++) {
7448 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7449 result = fill_port_2(info, &info[i].info2, qlines[i]);
7450 if (!W_ERROR_IS_OK(result)) {
7451 goto out;
7455 TALLOC_FREE(qlines);
7457 out:
7458 if (!W_ERROR_IS_OK(result)) {
7459 TALLOC_FREE(info);
7460 TALLOC_FREE(qlines);
7461 *count = 0;
7462 *info_p = NULL;
7463 return result;
7466 *info_p = info;
7467 *count = numlines;
7469 return WERR_OK;
7472 /****************************************************************
7473 _spoolss_EnumPorts
7474 ****************************************************************/
7476 WERROR _spoolss_EnumPorts(pipes_struct *p,
7477 struct spoolss_EnumPorts *r)
7479 WERROR result;
7481 /* that's an [in out] buffer */
7483 if (!r->in.buffer && (r->in.offered != 0)) {
7484 return WERR_INVALID_PARAM;
7487 DEBUG(4,("_spoolss_EnumPorts\n"));
7489 *r->out.count = 0;
7490 *r->out.needed = 0;
7491 *r->out.info = NULL;
7493 switch (r->in.level) {
7494 case 1:
7495 result = enumports_level_1(p->mem_ctx, r->out.info,
7496 r->out.count);
7497 break;
7498 case 2:
7499 result = enumports_level_2(p->mem_ctx, r->out.info,
7500 r->out.count);
7501 break;
7502 default:
7503 return WERR_UNKNOWN_LEVEL;
7506 if (!W_ERROR_IS_OK(result)) {
7507 return result;
7510 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7511 spoolss_EnumPorts, NULL,
7512 *r->out.info, r->in.level,
7513 *r->out.count);
7514 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7515 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7517 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7520 /****************************************************************************
7521 ****************************************************************************/
7523 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7524 const char *server,
7525 struct spoolss_SetPrinterInfoCtr *info_ctr,
7526 struct spoolss_DeviceMode *devmode,
7527 struct security_descriptor *sec_desc,
7528 struct spoolss_UserLevelCtr *user_ctr,
7529 struct policy_handle *handle)
7531 NT_PRINTER_INFO_LEVEL *printer = NULL;
7532 fstring name;
7533 int snum;
7534 WERROR err = WERR_OK;
7536 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7537 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7538 return WERR_NOMEM;
7541 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7542 if (!convert_printer_info(info_ctr, printer)) {
7543 free_a_printer(&printer, 2);
7544 return WERR_NOMEM;
7547 /* check to see if the printer already exists */
7549 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7550 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7551 printer->info_2->sharename));
7552 free_a_printer(&printer, 2);
7553 return WERR_PRINTER_ALREADY_EXISTS;
7556 /* FIXME!!! smbd should check to see if the driver is installed before
7557 trying to add a printer like this --jerry */
7559 if (*lp_addprinter_cmd() ) {
7560 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7561 printer) ) {
7562 free_a_printer(&printer,2);
7563 return WERR_ACCESS_DENIED;
7565 } else {
7566 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7567 "smb.conf parameter \"addprinter command\" is defined. This"
7568 "parameter must exist for this call to succeed\n",
7569 printer->info_2->sharename ));
7572 /* use our primary netbios name since get_a_printer() will convert
7573 it to what the client expects on a case by case basis */
7575 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7576 printer->info_2->sharename);
7579 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7580 free_a_printer(&printer,2);
7581 return WERR_ACCESS_DENIED;
7584 /* you must be a printer admin to add a new printer */
7585 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7586 free_a_printer(&printer,2);
7587 return WERR_ACCESS_DENIED;
7591 * Do sanity check on the requested changes for Samba.
7594 if (!check_printer_ok(printer->info_2, snum)) {
7595 free_a_printer(&printer,2);
7596 return WERR_INVALID_PARAM;
7600 * When a printer is created, the drivername bound to the printer is used
7601 * to lookup previously saved driver initialization info, which is then
7602 * bound to the new printer, simulating what happens in the Windows arch.
7605 if (!devmode)
7607 set_driver_init(printer, 2);
7609 else
7611 /* A valid devmode was included, convert and link it
7613 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7615 if (!convert_devicemode(printer->info_2->printername, devmode,
7616 &printer->info_2->devmode)) {
7617 return WERR_NOMEM;
7621 /* write the ASCII on disk */
7622 err = mod_a_printer(printer, 2);
7623 if (!W_ERROR_IS_OK(err)) {
7624 free_a_printer(&printer,2);
7625 return err;
7628 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7629 /* Handle open failed - remove addition. */
7630 del_a_printer(printer->info_2->sharename);
7631 free_a_printer(&printer,2);
7632 ZERO_STRUCTP(handle);
7633 return WERR_ACCESS_DENIED;
7636 update_c_setprinter(false);
7637 free_a_printer(&printer,2);
7639 return WERR_OK;
7642 /****************************************************************
7643 _spoolss_AddPrinterEx
7644 ****************************************************************/
7646 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7647 struct spoolss_AddPrinterEx *r)
7649 switch (r->in.info_ctr->level) {
7650 case 1:
7651 /* we don't handle yet */
7652 /* but I know what to do ... */
7653 return WERR_UNKNOWN_LEVEL;
7654 case 2:
7655 return spoolss_addprinterex_level_2(p, r->in.server,
7656 r->in.info_ctr,
7657 r->in.devmode_ctr->devmode,
7658 r->in.secdesc_ctr->sd,
7659 r->in.userlevel_ctr,
7660 r->out.handle);
7661 default:
7662 return WERR_UNKNOWN_LEVEL;
7666 /****************************************************************
7667 _spoolss_AddPrinter
7668 ****************************************************************/
7670 WERROR _spoolss_AddPrinter(pipes_struct *p,
7671 struct spoolss_AddPrinter *r)
7673 struct spoolss_AddPrinterEx a;
7674 struct spoolss_UserLevelCtr userlevel_ctr;
7676 ZERO_STRUCT(userlevel_ctr);
7678 userlevel_ctr.level = 1;
7680 a.in.server = r->in.server;
7681 a.in.info_ctr = r->in.info_ctr;
7682 a.in.devmode_ctr = r->in.devmode_ctr;
7683 a.in.secdesc_ctr = r->in.secdesc_ctr;
7684 a.in.userlevel_ctr = &userlevel_ctr;
7685 a.out.handle = r->out.handle;
7687 return _spoolss_AddPrinterEx(p, &a);
7690 /****************************************************************
7691 _spoolss_AddPrinterDriver
7692 ****************************************************************/
7694 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7695 struct spoolss_AddPrinterDriver *r)
7697 uint32_t level = r->in.info_ctr->level;
7698 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7699 WERROR err = WERR_OK;
7700 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7701 const char *driver_name = NULL;
7702 uint32_t version;
7703 const char *fn;
7705 switch (p->hdr_req.opnum) {
7706 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7707 fn = "_spoolss_AddPrinterDriver";
7708 break;
7709 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7710 fn = "_spoolss_AddPrinterDriverEx";
7711 break;
7712 default:
7713 return WERR_INVALID_PARAM;
7717 /* FIXME */
7718 if (level != 3 && level != 6) {
7719 /* Clever hack from Martin Zielinski <mz@seh.de>
7720 * to allow downgrade from level 8 (Vista).
7722 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7723 return WERR_UNKNOWN_LEVEL;
7726 ZERO_STRUCT(driver);
7728 if (!convert_printer_driver_info(info, &driver, level)) {
7729 err = WERR_NOMEM;
7730 goto done;
7733 DEBUG(5,("Cleaning driver's information\n"));
7734 err = clean_up_driver_struct(p, driver, level);
7735 if (!W_ERROR_IS_OK(err))
7736 goto done;
7738 DEBUG(5,("Moving driver to final destination\n"));
7739 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7740 &err)) ) {
7741 goto done;
7744 if (add_a_printer_driver(driver, level)!=0) {
7745 err = WERR_ACCESS_DENIED;
7746 goto done;
7749 switch(level) {
7750 case 3:
7751 driver_name = driver.info_3->name ? driver.info_3->name : "";
7752 break;
7753 case 6:
7754 driver_name = driver.info_6->name ? driver.info_6->name : "";
7755 break;
7759 * I think this is where he DrvUpgradePrinter() hook would be
7760 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7761 * server. Right now, we just need to send ourselves a message
7762 * to update each printer bound to this driver. --jerry
7765 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7766 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7767 fn, driver_name));
7771 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7772 * decide if the driver init data should be deleted. The rules are:
7773 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7774 * 2) delete init data only if there is no 2k/Xp driver
7775 * 3) always delete init data
7776 * The generalized rule is always use init data from the highest order driver.
7777 * It is necessary to follow the driver install by an initialization step to
7778 * finish off this process.
7780 if (level == 3)
7781 version = driver.info_3->cversion;
7782 else if (level == 6)
7783 version = driver.info_6->version;
7784 else
7785 version = -1;
7786 switch (version) {
7788 * 9x printer driver - never delete init data
7790 case 0:
7791 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7792 fn, driver_name));
7793 break;
7796 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7797 * there is no 2k/Xp driver init data for this driver name.
7799 case 2:
7801 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7803 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7805 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7807 if (!del_driver_init(driver_name))
7808 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7809 fn, driver_name));
7810 } else {
7812 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7814 free_a_printer_driver(driver1,3);
7815 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7816 fn, driver_name));
7819 break;
7822 * 2k or Xp printer driver - always delete init data
7824 case 3:
7825 if (!del_driver_init(driver_name))
7826 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7827 fn, driver_name));
7828 break;
7830 default:
7831 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7832 break;
7836 done:
7837 free_a_printer_driver(driver, level);
7838 return err;
7841 /****************************************************************
7842 _spoolss_AddPrinterDriverEx
7843 ****************************************************************/
7845 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7846 struct spoolss_AddPrinterDriverEx *r)
7848 struct spoolss_AddPrinterDriver a;
7851 * we only support the semantics of AddPrinterDriver()
7852 * i.e. only copy files that are newer than existing ones
7855 if (r->in.flags != APD_COPY_NEW_FILES) {
7856 return WERR_ACCESS_DENIED;
7859 a.in.servername = r->in.servername;
7860 a.in.info_ctr = r->in.info_ctr;
7862 return _spoolss_AddPrinterDriver(p, &a);
7865 /****************************************************************************
7866 ****************************************************************************/
7868 struct _spoolss_paths {
7869 int type;
7870 const char *share;
7871 const char *dir;
7874 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7876 static const struct _spoolss_paths spoolss_paths[]= {
7877 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7878 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7881 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7882 const char *servername,
7883 const char *environment,
7884 int component,
7885 char **path)
7887 const char *pservername = NULL;
7888 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7889 const char *short_archi;
7891 *path = NULL;
7893 /* environment may be empty */
7894 if (environment && strlen(environment)) {
7895 long_archi = environment;
7898 /* servername may be empty */
7899 if (servername && strlen(servername)) {
7900 pservername = canon_servername(servername);
7902 if (!is_myname_or_ipaddr(pservername)) {
7903 return WERR_INVALID_PARAM;
7907 if (!(short_archi = get_short_archi(long_archi))) {
7908 return WERR_INVALID_ENVIRONMENT;
7911 switch (component) {
7912 case SPOOLSS_PRTPROCS_PATH:
7913 case SPOOLSS_DRIVER_PATH:
7914 if (pservername) {
7915 *path = talloc_asprintf(mem_ctx,
7916 "\\\\%s\\%s\\%s",
7917 pservername,
7918 spoolss_paths[component].share,
7919 short_archi);
7920 } else {
7921 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7922 SPOOLSS_DEFAULT_SERVER_PATH,
7923 spoolss_paths[component].dir,
7924 short_archi);
7926 break;
7927 default:
7928 return WERR_INVALID_PARAM;
7931 if (!*path) {
7932 return WERR_NOMEM;
7935 return WERR_OK;
7938 /****************************************************************************
7939 ****************************************************************************/
7941 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7942 const char *servername,
7943 const char *environment,
7944 struct spoolss_DriverDirectoryInfo1 *r)
7946 WERROR werr;
7947 char *path = NULL;
7949 werr = compose_spoolss_server_path(mem_ctx,
7950 servername,
7951 environment,
7952 SPOOLSS_DRIVER_PATH,
7953 &path);
7954 if (!W_ERROR_IS_OK(werr)) {
7955 return werr;
7958 DEBUG(4,("printer driver directory: [%s]\n", path));
7960 r->directory_name = path;
7962 return WERR_OK;
7965 /****************************************************************
7966 _spoolss_GetPrinterDriverDirectory
7967 ****************************************************************/
7969 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7970 struct spoolss_GetPrinterDriverDirectory *r)
7972 WERROR werror;
7974 /* that's an [in out] buffer */
7976 if (!r->in.buffer && (r->in.offered != 0)) {
7977 return WERR_INVALID_PARAM;
7980 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7981 r->in.level));
7983 *r->out.needed = 0;
7985 /* r->in.level is ignored */
7987 werror = getprinterdriverdir_level_1(p->mem_ctx,
7988 r->in.server,
7989 r->in.environment,
7990 &r->out.info->info1);
7991 if (!W_ERROR_IS_OK(werror)) {
7992 TALLOC_FREE(r->out.info);
7993 return werror;
7996 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7997 r->out.info, r->in.level);
7998 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8000 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8003 /****************************************************************
8004 _spoolss_EnumPrinterData
8005 ****************************************************************/
8007 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
8008 struct spoolss_EnumPrinterData *r)
8010 NT_PRINTER_INFO_LEVEL *printer = NULL;
8011 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8012 int snum;
8013 WERROR result;
8014 struct regval_blob *val = NULL;
8015 NT_PRINTER_DATA *p_data;
8016 int i, key_index, num_values;
8017 int name_length;
8019 *r->out.value_needed = 0;
8020 *r->out.type = REG_NONE;
8021 *r->out.data_needed = 0;
8023 DEBUG(5,("_spoolss_EnumPrinterData\n"));
8025 if (!Printer) {
8026 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
8027 OUR_HANDLE(r->in.handle)));
8028 return WERR_BADFID;
8031 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8032 return WERR_BADFID;
8035 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8036 if (!W_ERROR_IS_OK(result)) {
8037 return result;
8040 p_data = printer->info_2->data;
8041 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8043 result = WERR_OK;
8046 * The NT machine wants to know the biggest size of value and data
8048 * cf: MSDN EnumPrinterData remark section
8051 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
8053 uint32_t biggest_valuesize = 0;
8054 uint32_t biggest_datasize = 0;
8056 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8058 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8060 for ( i=0; i<num_values; i++ )
8062 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8064 name_length = strlen(val->valuename);
8065 if ( strlen(val->valuename) > biggest_valuesize )
8066 biggest_valuesize = name_length;
8068 if ( val->size > biggest_datasize )
8069 biggest_datasize = val->size;
8071 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8072 biggest_datasize));
8075 /* the value is an UNICODE string but real_value_size is the length
8076 in bytes including the trailing 0 */
8078 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8079 *r->out.data_needed = biggest_datasize;
8081 DEBUG(6,("final values: [%d], [%d]\n",
8082 *r->out.value_needed, *r->out.data_needed));
8084 goto done;
8088 * the value len is wrong in NT sp3
8089 * that's the number of bytes not the number of unicode chars
8092 if (key_index != -1) {
8093 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8094 r->in.enum_index);
8097 if (!val) {
8099 /* out_value should default to "" or else NT4 has
8100 problems unmarshalling the response */
8102 if (r->in.value_offered) {
8103 *r->out.value_needed = 1;
8104 r->out.value_name = talloc_strdup(r, "");
8105 if (!r->out.value_name) {
8106 result = WERR_NOMEM;
8107 goto done;
8109 } else {
8110 r->out.value_name = NULL;
8111 *r->out.value_needed = 0;
8114 /* the data is counted in bytes */
8116 *r->out.data_needed = r->in.data_offered;
8118 result = WERR_NO_MORE_ITEMS;
8119 } else {
8121 * the value is:
8122 * - counted in bytes in the request
8123 * - counted in UNICODE chars in the max reply
8124 * - counted in bytes in the real size
8126 * take a pause *before* coding not *during* coding
8129 /* name */
8130 if (r->in.value_offered) {
8131 r->out.value_name = talloc_strdup(r, regval_name(val));
8132 if (!r->out.value_name) {
8133 result = WERR_NOMEM;
8134 goto done;
8136 *r->out.value_needed = strlen_m(regval_name(val));
8137 } else {
8138 r->out.value_name = NULL;
8139 *r->out.value_needed = 0;
8142 /* type */
8144 *r->out.type = regval_type(val);
8146 /* data - counted in bytes */
8148 if (r->out.data && regval_size(val)) {
8149 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8152 *r->out.data_needed = regval_size(val);
8155 done:
8156 free_a_printer(&printer, 2);
8157 return result;
8160 /****************************************************************
8161 _spoolss_SetPrinterData
8162 ****************************************************************/
8164 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8165 struct spoolss_SetPrinterData *r)
8167 NT_PRINTER_INFO_LEVEL *printer = NULL;
8168 int snum=0;
8169 WERROR result = WERR_OK;
8170 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8171 DATA_BLOB blob;
8173 DEBUG(5,("_spoolss_SetPrinterData\n"));
8175 if (!Printer) {
8176 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8177 OUR_HANDLE(r->in.handle)));
8178 return WERR_BADFID;
8181 if (Printer->printer_type == SPLHND_SERVER) {
8182 DEBUG(10,("_spoolss_SetPrinterData: "
8183 "Not implemented for server handles yet\n"));
8184 return WERR_INVALID_PARAM;
8187 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8188 return WERR_BADFID;
8192 * Access check : NT returns "access denied" if you make a
8193 * SetPrinterData call without the necessary privildge.
8194 * we were originally returning OK if nothing changed
8195 * which made Win2k issue **a lot** of SetPrinterData
8196 * when connecting to a printer --jerry
8199 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8200 DEBUG(3,("_spoolss_SetPrinterData: "
8201 "change denied by handle access permissions\n"));
8202 result = WERR_ACCESS_DENIED;
8203 goto done;
8206 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8207 if (!W_ERROR_IS_OK(result)) {
8208 return result;
8211 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8212 r->in.type, &r->in.data);
8213 if (!W_ERROR_IS_OK(result)) {
8214 goto done;
8218 * When client side code sets a magic printer data key, detect it and save
8219 * the current printer data and the magic key's data (its the DEVMODE) for
8220 * future printer/driver initializations.
8222 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8223 /* Set devmode and printer initialization info */
8224 result = save_driver_init(printer, 2, blob.data, blob.length);
8226 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8228 goto done;
8231 result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8232 r->in.value_name, r->in.type,
8233 blob.data, blob.length);
8234 if (W_ERROR_IS_OK(result)) {
8235 result = mod_a_printer(printer, 2);
8238 done:
8239 free_a_printer(&printer, 2);
8241 return result;
8244 /****************************************************************
8245 _spoolss_ResetPrinter
8246 ****************************************************************/
8248 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8249 struct spoolss_ResetPrinter *r)
8251 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8252 int snum;
8254 DEBUG(5,("_spoolss_ResetPrinter\n"));
8257 * All we do is to check to see if the handle and queue is valid.
8258 * This call really doesn't mean anything to us because we only
8259 * support RAW printing. --jerry
8262 if (!Printer) {
8263 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8264 OUR_HANDLE(r->in.handle)));
8265 return WERR_BADFID;
8268 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8269 return WERR_BADFID;
8272 /* blindly return success */
8273 return WERR_OK;
8276 /****************************************************************
8277 _spoolss_DeletePrinterData
8278 ****************************************************************/
8280 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8281 struct spoolss_DeletePrinterData *r)
8283 NT_PRINTER_INFO_LEVEL *printer = NULL;
8284 int snum=0;
8285 WERROR status = WERR_OK;
8286 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8288 DEBUG(5,("_spoolss_DeletePrinterData\n"));
8290 if (!Printer) {
8291 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8292 OUR_HANDLE(r->in.handle)));
8293 return WERR_BADFID;
8296 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8297 return WERR_BADFID;
8299 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8300 DEBUG(3, ("_spoolss_DeletePrinterData: "
8301 "printer properties change denied by handle\n"));
8302 return WERR_ACCESS_DENIED;
8305 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8306 if (!W_ERROR_IS_OK(status))
8307 return status;
8309 if (!r->in.value_name) {
8310 free_a_printer(&printer, 2);
8311 return WERR_NOMEM;
8314 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8315 r->in.value_name );
8317 if ( W_ERROR_IS_OK(status) )
8318 mod_a_printer( printer, 2 );
8320 free_a_printer(&printer, 2);
8322 return status;
8325 /****************************************************************
8326 _spoolss_AddForm
8327 ****************************************************************/
8329 WERROR _spoolss_AddForm(pipes_struct *p,
8330 struct spoolss_AddForm *r)
8332 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8333 nt_forms_struct tmpForm;
8334 int snum = -1;
8335 WERROR status = WERR_OK;
8336 NT_PRINTER_INFO_LEVEL *printer = NULL;
8337 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8339 int count=0;
8340 nt_forms_struct *list=NULL;
8341 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8343 DEBUG(5,("_spoolss_AddForm\n"));
8345 if (!Printer) {
8346 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8347 OUR_HANDLE(r->in.handle)));
8348 return WERR_BADFID;
8352 /* forms can be added on printer of on the print server handle */
8354 if ( Printer->printer_type == SPLHND_PRINTER )
8356 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8357 return WERR_BADFID;
8359 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8360 if (!W_ERROR_IS_OK(status))
8361 goto done;
8364 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8365 and not a printer admin, then fail */
8367 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8368 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8369 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8370 NULL, NULL,
8371 p->server_info->ptok,
8372 lp_printer_admin(snum))) {
8373 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8374 return WERR_ACCESS_DENIED;
8377 /* can't add if builtin */
8379 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8380 status = WERR_FILE_EXISTS;
8381 goto done;
8384 count = get_ntforms(&list);
8386 if(!add_a_form(&list, form, &count)) {
8387 status = WERR_NOMEM;
8388 goto done;
8391 become_root();
8392 write_ntforms(&list, count);
8393 unbecome_root();
8396 * ChangeID must always be set if this is a printer
8399 if ( Printer->printer_type == SPLHND_PRINTER )
8400 status = mod_a_printer(printer, 2);
8402 done:
8403 if ( printer )
8404 free_a_printer(&printer, 2);
8405 SAFE_FREE(list);
8407 return status;
8410 /****************************************************************
8411 _spoolss_DeleteForm
8412 ****************************************************************/
8414 WERROR _spoolss_DeleteForm(pipes_struct *p,
8415 struct spoolss_DeleteForm *r)
8417 const char *form_name = r->in.form_name;
8418 nt_forms_struct tmpForm;
8419 int count=0;
8420 nt_forms_struct *list=NULL;
8421 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8422 int snum = -1;
8423 WERROR status = WERR_OK;
8424 NT_PRINTER_INFO_LEVEL *printer = NULL;
8425 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8426 bool ret = false;
8428 DEBUG(5,("_spoolss_DeleteForm\n"));
8430 if (!Printer) {
8431 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8432 OUR_HANDLE(r->in.handle)));
8433 return WERR_BADFID;
8436 /* forms can be deleted on printer of on the print server handle */
8438 if ( Printer->printer_type == SPLHND_PRINTER )
8440 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8441 return WERR_BADFID;
8443 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8444 if (!W_ERROR_IS_OK(status))
8445 goto done;
8448 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8449 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8450 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8451 NULL, NULL,
8452 p->server_info->ptok,
8453 lp_printer_admin(snum))) {
8454 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8455 return WERR_ACCESS_DENIED;
8459 /* can't delete if builtin */
8461 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8462 status = WERR_INVALID_PARAM;
8463 goto done;
8466 count = get_ntforms(&list);
8468 become_root();
8469 ret = delete_a_form(&list, form_name, &count, &status);
8470 unbecome_root();
8471 if (ret == false) {
8472 goto done;
8476 * ChangeID must always be set if this is a printer
8479 if ( Printer->printer_type == SPLHND_PRINTER )
8480 status = mod_a_printer(printer, 2);
8482 done:
8483 if ( printer )
8484 free_a_printer(&printer, 2);
8485 SAFE_FREE(list);
8487 return status;
8490 /****************************************************************
8491 _spoolss_SetForm
8492 ****************************************************************/
8494 WERROR _spoolss_SetForm(pipes_struct *p,
8495 struct spoolss_SetForm *r)
8497 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8498 nt_forms_struct tmpForm;
8499 int snum = -1;
8500 WERROR status = WERR_OK;
8501 NT_PRINTER_INFO_LEVEL *printer = NULL;
8502 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8504 int count=0;
8505 nt_forms_struct *list=NULL;
8506 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8508 DEBUG(5,("_spoolss_SetForm\n"));
8510 if (!Printer) {
8511 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8512 OUR_HANDLE(r->in.handle)));
8513 return WERR_BADFID;
8516 /* forms can be modified on printer of on the print server handle */
8518 if ( Printer->printer_type == SPLHND_PRINTER )
8520 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8521 return WERR_BADFID;
8523 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8524 if (!W_ERROR_IS_OK(status))
8525 goto done;
8528 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8529 and not a printer admin, then fail */
8531 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8532 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8533 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8534 NULL, NULL,
8535 p->server_info->ptok,
8536 lp_printer_admin(snum))) {
8537 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8538 return WERR_ACCESS_DENIED;
8541 /* can't set if builtin */
8542 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8543 status = WERR_INVALID_PARAM;
8544 goto done;
8547 count = get_ntforms(&list);
8548 update_a_form(&list, form, count);
8549 become_root();
8550 write_ntforms(&list, count);
8551 unbecome_root();
8554 * ChangeID must always be set if this is a printer
8557 if ( Printer->printer_type == SPLHND_PRINTER )
8558 status = mod_a_printer(printer, 2);
8561 done:
8562 if ( printer )
8563 free_a_printer(&printer, 2);
8564 SAFE_FREE(list);
8566 return status;
8569 /****************************************************************************
8570 fill_print_processor1
8571 ****************************************************************************/
8573 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8574 struct spoolss_PrintProcessorInfo1 *r,
8575 const char *print_processor_name)
8577 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8578 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8580 return WERR_OK;
8583 /****************************************************************************
8584 enumprintprocessors level 1.
8585 ****************************************************************************/
8587 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8588 union spoolss_PrintProcessorInfo **info_p,
8589 uint32_t *count)
8591 union spoolss_PrintProcessorInfo *info;
8592 WERROR result;
8594 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8595 W_ERROR_HAVE_NO_MEMORY(info);
8597 *count = 1;
8599 result = fill_print_processor1(info, &info[0].info1, "winprint");
8600 if (!W_ERROR_IS_OK(result)) {
8601 goto out;
8604 out:
8605 if (!W_ERROR_IS_OK(result)) {
8606 TALLOC_FREE(info);
8607 *count = 0;
8608 return result;
8611 *info_p = info;
8613 return WERR_OK;
8616 /****************************************************************
8617 _spoolss_EnumPrintProcessors
8618 ****************************************************************/
8620 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8621 struct spoolss_EnumPrintProcessors *r)
8623 WERROR result;
8625 /* that's an [in out] buffer */
8627 if (!r->in.buffer && (r->in.offered != 0)) {
8628 return WERR_INVALID_PARAM;
8631 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8634 * Enumerate the print processors ...
8636 * Just reply with "winprint", to keep NT happy
8637 * and I can use my nice printer checker.
8640 *r->out.count = 0;
8641 *r->out.needed = 0;
8642 *r->out.info = NULL;
8644 switch (r->in.level) {
8645 case 1:
8646 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8647 r->out.count);
8648 break;
8649 default:
8650 return WERR_UNKNOWN_LEVEL;
8653 if (!W_ERROR_IS_OK(result)) {
8654 return result;
8657 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8658 spoolss_EnumPrintProcessors, NULL,
8659 *r->out.info, r->in.level,
8660 *r->out.count);
8661 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8662 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8664 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8667 /****************************************************************************
8668 fill_printprocdatatype1
8669 ****************************************************************************/
8671 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8672 struct spoolss_PrintProcDataTypesInfo1 *r,
8673 const char *name_array)
8675 r->name_array = talloc_strdup(mem_ctx, name_array);
8676 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8678 return WERR_OK;
8681 /****************************************************************************
8682 enumprintprocdatatypes level 1.
8683 ****************************************************************************/
8685 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8686 union spoolss_PrintProcDataTypesInfo **info_p,
8687 uint32_t *count)
8689 WERROR result;
8690 union spoolss_PrintProcDataTypesInfo *info;
8692 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8693 W_ERROR_HAVE_NO_MEMORY(info);
8695 *count = 1;
8697 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8698 if (!W_ERROR_IS_OK(result)) {
8699 goto out;
8702 out:
8703 if (!W_ERROR_IS_OK(result)) {
8704 TALLOC_FREE(info);
8705 *count = 0;
8706 return result;
8709 *info_p = info;
8711 return WERR_OK;
8714 /****************************************************************
8715 _spoolss_EnumPrintProcDataTypes
8716 ****************************************************************/
8718 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8719 struct spoolss_EnumPrintProcDataTypes *r)
8721 WERROR result;
8723 /* that's an [in out] buffer */
8725 if (!r->in.buffer && (r->in.offered != 0)) {
8726 return WERR_INVALID_PARAM;
8729 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8731 *r->out.count = 0;
8732 *r->out.needed = 0;
8733 *r->out.info = NULL;
8735 switch (r->in.level) {
8736 case 1:
8737 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8738 r->out.count);
8739 break;
8740 default:
8741 return WERR_UNKNOWN_LEVEL;
8744 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8745 spoolss_EnumPrintProcDataTypes, NULL,
8746 *r->out.info, r->in.level,
8747 *r->out.count);
8748 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8749 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8751 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8754 /****************************************************************************
8755 fill_monitor_1
8756 ****************************************************************************/
8758 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8759 struct spoolss_MonitorInfo1 *r,
8760 const char *monitor_name)
8762 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8763 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8765 return WERR_OK;
8768 /****************************************************************************
8769 fill_monitor_2
8770 ****************************************************************************/
8772 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8773 struct spoolss_MonitorInfo2 *r,
8774 const char *monitor_name,
8775 const char *environment,
8776 const char *dll_name)
8778 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8779 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8780 r->environment = talloc_strdup(mem_ctx, environment);
8781 W_ERROR_HAVE_NO_MEMORY(r->environment);
8782 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8783 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8785 return WERR_OK;
8788 /****************************************************************************
8789 enumprintmonitors level 1.
8790 ****************************************************************************/
8792 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8793 union spoolss_MonitorInfo **info_p,
8794 uint32_t *count)
8796 union spoolss_MonitorInfo *info;
8797 WERROR result = WERR_OK;
8799 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8800 W_ERROR_HAVE_NO_MEMORY(info);
8802 *count = 2;
8804 result = fill_monitor_1(info, &info[0].info1,
8805 SPL_LOCAL_PORT);
8806 if (!W_ERROR_IS_OK(result)) {
8807 goto out;
8810 result = fill_monitor_1(info, &info[1].info1,
8811 SPL_TCPIP_PORT);
8812 if (!W_ERROR_IS_OK(result)) {
8813 goto out;
8816 out:
8817 if (!W_ERROR_IS_OK(result)) {
8818 TALLOC_FREE(info);
8819 *count = 0;
8820 return result;
8823 *info_p = info;
8825 return WERR_OK;
8828 /****************************************************************************
8829 enumprintmonitors level 2.
8830 ****************************************************************************/
8832 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8833 union spoolss_MonitorInfo **info_p,
8834 uint32_t *count)
8836 union spoolss_MonitorInfo *info;
8837 WERROR result = WERR_OK;
8839 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8840 W_ERROR_HAVE_NO_MEMORY(info);
8842 *count = 2;
8844 result = fill_monitor_2(info, &info[0].info2,
8845 SPL_LOCAL_PORT,
8846 "Windows NT X86", /* FIXME */
8847 "localmon.dll");
8848 if (!W_ERROR_IS_OK(result)) {
8849 goto out;
8852 result = fill_monitor_2(info, &info[1].info2,
8853 SPL_TCPIP_PORT,
8854 "Windows NT X86", /* FIXME */
8855 "tcpmon.dll");
8856 if (!W_ERROR_IS_OK(result)) {
8857 goto out;
8860 out:
8861 if (!W_ERROR_IS_OK(result)) {
8862 TALLOC_FREE(info);
8863 *count = 0;
8864 return result;
8867 *info_p = info;
8869 return WERR_OK;
8872 /****************************************************************
8873 _spoolss_EnumMonitors
8874 ****************************************************************/
8876 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8877 struct spoolss_EnumMonitors *r)
8879 WERROR result;
8881 /* that's an [in out] buffer */
8883 if (!r->in.buffer && (r->in.offered != 0)) {
8884 return WERR_INVALID_PARAM;
8887 DEBUG(5,("_spoolss_EnumMonitors\n"));
8890 * Enumerate the print monitors ...
8892 * Just reply with "Local Port", to keep NT happy
8893 * and I can use my nice printer checker.
8896 *r->out.count = 0;
8897 *r->out.needed = 0;
8898 *r->out.info = NULL;
8900 switch (r->in.level) {
8901 case 1:
8902 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8903 r->out.count);
8904 break;
8905 case 2:
8906 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8907 r->out.count);
8908 break;
8909 default:
8910 return WERR_UNKNOWN_LEVEL;
8913 if (!W_ERROR_IS_OK(result)) {
8914 return result;
8917 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8918 spoolss_EnumMonitors, NULL,
8919 *r->out.info, r->in.level,
8920 *r->out.count);
8921 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8922 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8924 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8927 /****************************************************************************
8928 ****************************************************************************/
8930 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8931 const print_queue_struct *queue,
8932 int count, int snum,
8933 const NT_PRINTER_INFO_LEVEL *ntprinter,
8934 uint32_t jobid,
8935 struct spoolss_JobInfo1 *r)
8937 int i = 0;
8938 bool found = false;
8940 for (i=0; i<count && found == false; i++) {
8941 if (queue[i].job == (int)jobid) {
8942 found = true;
8946 if (found == false) {
8947 /* NT treats not found as bad param... yet another bad choice */
8948 return WERR_INVALID_PARAM;
8951 return fill_job_info1(mem_ctx,
8953 &queue[i-1],
8955 snum,
8956 ntprinter);
8959 /****************************************************************************
8960 ****************************************************************************/
8962 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8963 const print_queue_struct *queue,
8964 int count, int snum,
8965 const NT_PRINTER_INFO_LEVEL *ntprinter,
8966 uint32_t jobid,
8967 struct spoolss_JobInfo2 *r)
8969 int i = 0;
8970 bool found = false;
8971 struct spoolss_DeviceMode *devmode;
8972 NT_DEVICEMODE *nt_devmode;
8973 WERROR result;
8975 for (i=0; i<count && found == false; i++) {
8976 if (queue[i].job == (int)jobid) {
8977 found = true;
8981 if (found == false) {
8982 /* NT treats not found as bad param... yet another bad
8983 choice */
8984 return WERR_INVALID_PARAM;
8988 * if the print job does not have a DEVMODE associated with it,
8989 * just use the one for the printer. A NULL devicemode is not
8990 * a failure condition
8993 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8994 if (nt_devmode) {
8995 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8996 W_ERROR_HAVE_NO_MEMORY(devmode);
8997 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8998 if (!W_ERROR_IS_OK(result)) {
8999 return result;
9001 } else {
9002 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
9003 W_ERROR_HAVE_NO_MEMORY(devmode);
9006 return fill_job_info2(mem_ctx,
9008 &queue[i-1],
9010 snum,
9011 ntprinter,
9012 devmode);
9015 /****************************************************************
9016 _spoolss_GetJob
9017 ****************************************************************/
9019 WERROR _spoolss_GetJob(pipes_struct *p,
9020 struct spoolss_GetJob *r)
9022 WERROR result = WERR_OK;
9023 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9024 int snum;
9025 int count;
9026 print_queue_struct *queue = NULL;
9027 print_status_struct prt_status;
9029 /* that's an [in out] buffer */
9031 if (!r->in.buffer && (r->in.offered != 0)) {
9032 return WERR_INVALID_PARAM;
9035 DEBUG(5,("_spoolss_GetJob\n"));
9037 *r->out.needed = 0;
9039 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9040 return WERR_BADFID;
9043 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9044 if (!W_ERROR_IS_OK(result)) {
9045 return result;
9048 count = print_queue_status(snum, &queue, &prt_status);
9050 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9051 count, prt_status.status, prt_status.message));
9053 switch (r->in.level) {
9054 case 1:
9055 result = getjob_level_1(p->mem_ctx,
9056 queue, count, snum, ntprinter,
9057 r->in.job_id, &r->out.info->info1);
9058 break;
9059 case 2:
9060 result = getjob_level_2(p->mem_ctx,
9061 queue, count, snum, ntprinter,
9062 r->in.job_id, &r->out.info->info2);
9063 break;
9064 default:
9065 result = WERR_UNKNOWN_LEVEL;
9066 break;
9069 SAFE_FREE(queue);
9070 free_a_printer(&ntprinter, 2);
9072 if (!W_ERROR_IS_OK(result)) {
9073 TALLOC_FREE(r->out.info);
9074 return result;
9077 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9078 r->out.info, r->in.level);
9079 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9081 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9084 /****************************************************************
9085 _spoolss_GetPrinterDataEx
9087 From MSDN documentation of GetPrinterDataEx: pass request
9088 to GetPrinterData if key is "PrinterDriverData".
9089 ****************************************************************/
9091 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9092 struct spoolss_GetPrinterDataEx *r)
9095 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9096 struct regval_blob *val = NULL;
9097 NT_PRINTER_INFO_LEVEL *printer = NULL;
9098 int snum = 0;
9099 WERROR result = WERR_OK;
9101 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9103 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9104 r->in.key_name, r->in.value_name));
9106 /* in case of problem, return some default values */
9108 *r->out.needed = 0;
9109 *r->out.type = REG_NONE;
9111 if (!Printer) {
9112 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9113 OUR_HANDLE(r->in.handle)));
9114 result = WERR_BADFID;
9115 goto done;
9118 /* Is the handle to a printer or to the server? */
9120 if (Printer->printer_type == SPLHND_SERVER) {
9121 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9122 "Not implemented for server handles yet\n"));
9123 result = WERR_INVALID_PARAM;
9124 goto done;
9127 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9128 return WERR_BADFID;
9131 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9132 if (!W_ERROR_IS_OK(result)) {
9133 goto done;
9136 /* check to see if the keyname is valid */
9137 if (!strlen(r->in.key_name)) {
9138 result = WERR_INVALID_PARAM;
9139 goto done;
9142 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9143 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9144 "Invalid keyname [%s]\n", r->in.key_name ));
9145 result = WERR_BADFILE;
9146 goto done;
9149 /* When given a new keyname, we should just create it */
9151 val = get_printer_data(printer->info_2,
9152 r->in.key_name, r->in.value_name);
9153 if (!val) {
9154 result = WERR_BADFILE;
9155 goto done;
9158 *r->out.needed = regval_size(val);
9160 if (*r->out.needed > r->in.offered) {
9161 result = WERR_MORE_DATA;
9162 goto done;
9165 *r->out.type = regval_type(val);
9167 memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
9169 done:
9170 if (printer) {
9171 free_a_printer(&printer, 2);
9174 return result;
9177 /****************************************************************
9178 _spoolss_SetPrinterDataEx
9179 ****************************************************************/
9181 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9182 struct spoolss_SetPrinterDataEx *r)
9184 NT_PRINTER_INFO_LEVEL *printer = NULL;
9185 int snum = 0;
9186 WERROR result = WERR_OK;
9187 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9188 char *oid_string;
9190 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9192 /* From MSDN documentation of SetPrinterDataEx: pass request to
9193 SetPrinterData if key is "PrinterDriverData" */
9195 if (!Printer) {
9196 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9197 OUR_HANDLE(r->in.handle)));
9198 return WERR_BADFID;
9201 if (Printer->printer_type == SPLHND_SERVER) {
9202 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9203 "Not implemented for server handles yet\n"));
9204 return WERR_INVALID_PARAM;
9207 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9208 return WERR_BADFID;
9212 * Access check : NT returns "access denied" if you make a
9213 * SetPrinterData call without the necessary privildge.
9214 * we were originally returning OK if nothing changed
9215 * which made Win2k issue **a lot** of SetPrinterData
9216 * when connecting to a printer --jerry
9219 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9220 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9221 "change denied by handle access permissions\n"));
9222 return WERR_ACCESS_DENIED;
9225 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9226 if (!W_ERROR_IS_OK(result)) {
9227 return result;
9230 /* check for OID in valuename */
9232 oid_string = strchr(r->in.value_name, ',');
9233 if (oid_string) {
9234 *oid_string = '\0';
9235 oid_string++;
9238 /* save the registry data */
9240 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9241 r->in.type, r->in.buffer, r->in.offered);
9243 if (W_ERROR_IS_OK(result)) {
9244 /* save the OID if one was specified */
9245 if (oid_string) {
9246 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9247 r->in.key_name, SPOOL_OID_KEY);
9248 if (!str) {
9249 result = WERR_NOMEM;
9250 goto done;
9254 * I'm not checking the status here on purpose. Don't know
9255 * if this is right, but I'm returning the status from the
9256 * previous set_printer_dataex() call. I have no idea if
9257 * this is right. --jerry
9260 set_printer_dataex(printer, str, r->in.value_name,
9261 REG_SZ, (uint8_t *)oid_string,
9262 strlen(oid_string)+1);
9265 result = mod_a_printer(printer, 2);
9268 done:
9269 free_a_printer(&printer, 2);
9271 return result;
9274 /****************************************************************
9275 _spoolss_DeletePrinterDataEx
9276 ****************************************************************/
9278 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9279 struct spoolss_DeletePrinterDataEx *r)
9281 NT_PRINTER_INFO_LEVEL *printer = NULL;
9282 int snum=0;
9283 WERROR status = WERR_OK;
9284 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9286 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9288 if (!Printer) {
9289 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9290 "Invalid handle (%s:%u:%u).\n",
9291 OUR_HANDLE(r->in.handle)));
9292 return WERR_BADFID;
9295 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9296 return WERR_BADFID;
9298 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9299 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9300 "printer properties change denied by handle\n"));
9301 return WERR_ACCESS_DENIED;
9304 if (!r->in.value_name || !r->in.key_name) {
9305 return WERR_NOMEM;
9308 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9309 if (!W_ERROR_IS_OK(status))
9310 return status;
9312 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9314 if ( W_ERROR_IS_OK(status) )
9315 mod_a_printer( printer, 2 );
9317 free_a_printer(&printer, 2);
9319 return status;
9322 /****************************************************************
9323 _spoolss_EnumPrinterKey
9324 ****************************************************************/
9326 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9327 struct spoolss_EnumPrinterKey *r)
9329 fstring *keynames = NULL;
9330 int num_keys;
9331 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9332 NT_PRINTER_DATA *data;
9333 NT_PRINTER_INFO_LEVEL *printer = NULL;
9334 int snum = 0;
9335 WERROR result = WERR_BADFILE;
9336 int i;
9337 const char **array = NULL;
9340 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9342 if (!Printer) {
9343 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9344 OUR_HANDLE(r->in.handle)));
9345 return WERR_BADFID;
9348 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9349 return WERR_BADFID;
9352 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9353 if (!W_ERROR_IS_OK(result)) {
9354 return result;
9357 /* get the list of subkey names */
9359 data = printer->info_2->data;
9361 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9362 if (num_keys == -1) {
9363 result = WERR_BADFILE;
9364 goto done;
9367 *r->out.needed = 4;
9369 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9370 if (!array) {
9371 result = WERR_NOMEM;
9372 goto done;
9375 for (i=0; i < num_keys; i++) {
9376 array[i] = talloc_strdup(array, keynames[i]);
9377 if (!array[i]) {
9378 result = WERR_NOMEM;
9379 goto done;
9382 *r->out.needed += strlen_m_term(keynames[i]) * 2;
9385 if (r->in.offered < *r->out.needed) {
9386 result = WERR_MORE_DATA;
9387 goto done;
9390 result = WERR_OK;
9392 *r->out.key_buffer = array;
9394 done:
9395 if (!W_ERROR_IS_OK(result)) {
9396 TALLOC_FREE(array);
9397 ZERO_STRUCTP(r->out.key_buffer);
9400 free_a_printer(&printer, 2);
9401 SAFE_FREE(keynames);
9403 return result;
9406 /****************************************************************
9407 _spoolss_DeletePrinterKey
9408 ****************************************************************/
9410 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9411 struct spoolss_DeletePrinterKey *r)
9413 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9414 NT_PRINTER_INFO_LEVEL *printer = NULL;
9415 int snum=0;
9416 WERROR status;
9418 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9420 if (!Printer) {
9421 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9422 OUR_HANDLE(r->in.handle)));
9423 return WERR_BADFID;
9426 /* if keyname == NULL, return error */
9428 if ( !r->in.key_name )
9429 return WERR_INVALID_PARAM;
9431 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9432 return WERR_BADFID;
9434 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9435 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9436 "printer properties change denied by handle\n"));
9437 return WERR_ACCESS_DENIED;
9440 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9441 if (!W_ERROR_IS_OK(status))
9442 return status;
9444 /* delete the key and all subneys */
9446 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9448 if ( W_ERROR_IS_OK(status) )
9449 status = mod_a_printer(printer, 2);
9451 free_a_printer( &printer, 2 );
9453 return status;
9456 /****************************************************************
9457 ****************************************************************/
9459 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9460 struct regval_blob *v,
9461 struct spoolss_PrinterEnumValues *r)
9463 WERROR result;
9465 r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9466 W_ERROR_HAVE_NO_MEMORY(r->data);
9468 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
9469 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9471 r->type = regval_type(v);
9472 r->data_length = regval_size(v);
9474 if (r->data_length) {
9475 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9476 regval_size(v));
9477 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9478 r->data,
9479 r->type);
9480 if (!W_ERROR_IS_OK(result)) {
9481 return result;
9485 return WERR_OK;
9488 /****************************************************************
9489 _spoolss_EnumPrinterDataEx
9490 ****************************************************************/
9492 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9493 struct spoolss_EnumPrinterDataEx *r)
9495 uint32_t count = 0;
9496 NT_PRINTER_INFO_LEVEL *printer = NULL;
9497 struct spoolss_PrinterEnumValues *info = NULL;
9498 NT_PRINTER_DATA *p_data;
9499 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9500 int snum;
9501 WERROR result;
9502 int key_index;
9503 int i;
9505 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9507 *r->out.count = 0;
9508 *r->out.needed = 0;
9509 *r->out.info = NULL;
9511 if (!Printer) {
9512 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9513 OUR_HANDLE(r->in.handle)));
9514 return WERR_BADFID;
9518 * first check for a keyname of NULL or "". Win2k seems to send
9519 * this a lot and we should send back WERR_INVALID_PARAM
9520 * no need to spend time looking up the printer in this case.
9521 * --jerry
9524 if (!strlen(r->in.key_name)) {
9525 result = WERR_INVALID_PARAM;
9526 goto done;
9529 /* get the printer off of disk */
9531 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9532 return WERR_BADFID;
9535 ZERO_STRUCT(printer);
9536 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9537 if (!W_ERROR_IS_OK(result)) {
9538 return result;
9541 /* now look for a match on the key name */
9543 p_data = printer->info_2->data;
9545 key_index = lookup_printerkey(p_data, r->in.key_name);
9546 if (key_index == -1) {
9547 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9548 r->in.key_name));
9549 result = WERR_INVALID_PARAM;
9550 goto done;
9553 /* allocate the memory for the array of pointers -- if necessary */
9555 count = regval_ctr_numvals(p_data->keys[key_index].values);
9556 if (!count) {
9557 result = WERR_OK; /* ??? */
9558 goto done;
9561 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9562 struct spoolss_PrinterEnumValues,
9563 count);
9564 if (!info) {
9565 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9566 result = WERR_NOMEM;
9567 goto done;
9571 * loop through all params and build the array to pass
9572 * back to the client
9575 for (i=0; i < count; i++) {
9577 struct regval_blob *val;
9579 /* lookup the registry value */
9581 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9583 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9585 /* copy the data */
9587 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9588 if (!W_ERROR_IS_OK(result)) {
9589 goto done;
9593 #if 0 /* FIXME - gd */
9594 /* housekeeping information in the reply */
9596 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9597 * the hand marshalled container size is a multiple
9598 * of 4 bytes for RPC alignment.
9601 if (needed % 4) {
9602 needed += 4-(needed % 4);
9604 #endif
9605 *r->out.count = count;
9606 *r->out.info = info;
9608 done:
9610 if (printer) {
9611 free_a_printer(&printer, 2);
9614 if (!W_ERROR_IS_OK(result)) {
9615 return result;
9618 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9619 spoolss_EnumPrinterDataEx, NULL,
9620 *r->out.info,
9621 *r->out.count);
9622 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9623 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9625 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9628 /****************************************************************************
9629 ****************************************************************************/
9631 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9632 const char *servername,
9633 const char *environment,
9634 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9636 WERROR werr;
9637 char *path = NULL;
9639 werr = compose_spoolss_server_path(mem_ctx,
9640 servername,
9641 environment,
9642 SPOOLSS_PRTPROCS_PATH,
9643 &path);
9644 if (!W_ERROR_IS_OK(werr)) {
9645 return werr;
9648 DEBUG(4,("print processor directory: [%s]\n", path));
9650 r->directory_name = path;
9652 return WERR_OK;
9655 /****************************************************************
9656 _spoolss_GetPrintProcessorDirectory
9657 ****************************************************************/
9659 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9660 struct spoolss_GetPrintProcessorDirectory *r)
9662 WERROR result;
9664 /* that's an [in out] buffer */
9666 if (!r->in.buffer && (r->in.offered != 0)) {
9667 return WERR_INVALID_PARAM;
9670 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9671 r->in.level));
9673 *r->out.needed = 0;
9675 /* r->in.level is ignored */
9677 /* We always should reply with a local print processor directory so that
9678 * users are not forced to have a [prnproc$] share on the Samba spoolss
9679 * server - Guenther */
9681 result = getprintprocessordirectory_level_1(p->mem_ctx,
9682 NULL, /* r->in.server */
9683 r->in.environment,
9684 &r->out.info->info1);
9685 if (!W_ERROR_IS_OK(result)) {
9686 TALLOC_FREE(r->out.info);
9687 return result;
9690 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9691 r->out.info, r->in.level);
9692 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9694 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9697 /*******************************************************************
9698 ********************************************************************/
9700 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9701 const char *dllname)
9703 enum ndr_err_code ndr_err;
9704 struct spoolss_MonitorUi ui;
9706 ui.dll_name = dllname;
9708 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9709 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9710 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9711 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9713 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9716 /*******************************************************************
9717 Streams the monitor UI DLL name in UNICODE
9718 *******************************************************************/
9720 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9721 NT_USER_TOKEN *token, DATA_BLOB *in,
9722 DATA_BLOB *out, uint32_t *needed)
9724 const char *dllname = "tcpmonui.dll";
9726 *needed = (strlen(dllname)+1) * 2;
9728 if (out->length < *needed) {
9729 return WERR_INSUFFICIENT_BUFFER;
9732 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9733 return WERR_NOMEM;
9736 return WERR_OK;
9739 /*******************************************************************
9740 ********************************************************************/
9742 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9743 struct spoolss_PortData1 *port1,
9744 const DATA_BLOB *buf)
9746 enum ndr_err_code ndr_err;
9747 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9748 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9749 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9750 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9752 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9755 /*******************************************************************
9756 ********************************************************************/
9758 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9759 struct spoolss_PortData2 *port2,
9760 const DATA_BLOB *buf)
9762 enum ndr_err_code ndr_err;
9763 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9764 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9765 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9766 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9768 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9771 /*******************************************************************
9772 Create a new TCP/IP port
9773 *******************************************************************/
9775 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9776 NT_USER_TOKEN *token, DATA_BLOB *in,
9777 DATA_BLOB *out, uint32_t *needed)
9779 struct spoolss_PortData1 port1;
9780 struct spoolss_PortData2 port2;
9781 char *device_uri = NULL;
9782 uint32_t version;
9784 const char *portname;
9785 const char *hostaddress;
9786 const char *queue;
9787 uint32_t port_number;
9788 uint32_t protocol;
9790 /* peek for spoolss_PortData version */
9792 if (!in || (in->length < (128 + 4))) {
9793 return WERR_GENERAL_FAILURE;
9796 version = IVAL(in->data, 128);
9798 switch (version) {
9799 case 1:
9800 ZERO_STRUCT(port1);
9802 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9803 return WERR_NOMEM;
9806 portname = port1.portname;
9807 hostaddress = port1.hostaddress;
9808 queue = port1.queue;
9809 protocol = port1.protocol;
9810 port_number = port1.port_number;
9812 break;
9813 case 2:
9814 ZERO_STRUCT(port2);
9816 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9817 return WERR_NOMEM;
9820 portname = port2.portname;
9821 hostaddress = port2.hostaddress;
9822 queue = port2.queue;
9823 protocol = port2.protocol;
9824 port_number = port2.port_number;
9826 break;
9827 default:
9828 DEBUG(1,("xcvtcp_addport: "
9829 "unknown version of port_data: %d\n", version));
9830 return WERR_UNKNOWN_PORT;
9833 /* create the device URI and call the add_port_hook() */
9835 switch (protocol) {
9836 case PROTOCOL_RAWTCP_TYPE:
9837 device_uri = talloc_asprintf(mem_ctx,
9838 "socket://%s:%d/", hostaddress,
9839 port_number);
9840 break;
9842 case PROTOCOL_LPR_TYPE:
9843 device_uri = talloc_asprintf(mem_ctx,
9844 "lpr://%s/%s", hostaddress, queue );
9845 break;
9847 default:
9848 return WERR_UNKNOWN_PORT;
9851 if (!device_uri) {
9852 return WERR_NOMEM;
9855 return add_port_hook(mem_ctx, token, portname, device_uri);
9858 /*******************************************************************
9859 *******************************************************************/
9861 struct xcv_api_table xcvtcp_cmds[] = {
9862 { "MonitorUI", xcvtcp_monitorui },
9863 { "AddPort", xcvtcp_addport},
9864 { NULL, NULL }
9867 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9868 NT_USER_TOKEN *token, const char *command,
9869 DATA_BLOB *inbuf,
9870 DATA_BLOB *outbuf,
9871 uint32_t *needed )
9873 int i;
9875 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9877 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9878 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9879 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9882 return WERR_BADFUNC;
9885 /*******************************************************************
9886 *******************************************************************/
9887 #if 0 /* don't support management using the "Local Port" monitor */
9889 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9890 NT_USER_TOKEN *token, DATA_BLOB *in,
9891 DATA_BLOB *out, uint32_t *needed)
9893 const char *dllname = "localui.dll";
9895 *needed = (strlen(dllname)+1) * 2;
9897 if (out->length < *needed) {
9898 return WERR_INSUFFICIENT_BUFFER;
9901 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9902 return WERR_NOMEM;
9905 return WERR_OK;
9908 /*******************************************************************
9909 *******************************************************************/
9911 struct xcv_api_table xcvlocal_cmds[] = {
9912 { "MonitorUI", xcvlocal_monitorui },
9913 { NULL, NULL }
9915 #else
9916 struct xcv_api_table xcvlocal_cmds[] = {
9917 { NULL, NULL }
9919 #endif
9923 /*******************************************************************
9924 *******************************************************************/
9926 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9927 NT_USER_TOKEN *token, const char *command,
9928 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9929 uint32_t *needed)
9931 int i;
9933 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9935 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9936 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9937 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9939 return WERR_BADFUNC;
9942 /****************************************************************
9943 _spoolss_XcvData
9944 ****************************************************************/
9946 WERROR _spoolss_XcvData(pipes_struct *p,
9947 struct spoolss_XcvData *r)
9949 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9950 DATA_BLOB out_data = data_blob_null;
9951 WERROR werror;
9953 if (!Printer) {
9954 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9955 OUR_HANDLE(r->in.handle)));
9956 return WERR_BADFID;
9959 /* Has to be a handle to the TCP/IP port monitor */
9961 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9962 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9963 return WERR_BADFID;
9966 /* requires administrative access to the server */
9968 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9969 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9970 return WERR_ACCESS_DENIED;
9973 /* Allocate the outgoing buffer */
9975 if (r->in.out_data_size) {
9976 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9977 if (out_data.data == NULL) {
9978 return WERR_NOMEM;
9982 switch ( Printer->printer_type ) {
9983 case SPLHND_PORTMON_TCP:
9984 werror = process_xcvtcp_command(p->mem_ctx,
9985 p->server_info->ptok,
9986 r->in.function_name,
9987 &r->in.in_data, &out_data,
9988 r->out.needed);
9989 break;
9990 case SPLHND_PORTMON_LOCAL:
9991 werror = process_xcvlocal_command(p->mem_ctx,
9992 p->server_info->ptok,
9993 r->in.function_name,
9994 &r->in.in_data, &out_data,
9995 r->out.needed);
9996 break;
9997 default:
9998 werror = WERR_INVALID_PRINT_MONITOR;
10001 if (!W_ERROR_IS_OK(werror)) {
10002 return werror;
10005 *r->out.status_code = 0;
10007 memcpy(r->out.out_data, out_data.data, out_data.length);
10009 return WERR_OK;
10012 /****************************************************************
10013 _spoolss_AddPrintProcessor
10014 ****************************************************************/
10016 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10017 struct spoolss_AddPrintProcessor *r)
10019 /* for now, just indicate success and ignore the add. We'll
10020 automatically set the winprint processor for printer
10021 entries later. Used to debug the LexMark Optra S 1855 PCL
10022 driver --jerry */
10024 return WERR_OK;
10027 /****************************************************************
10028 _spoolss_AddPort
10029 ****************************************************************/
10031 WERROR _spoolss_AddPort(pipes_struct *p,
10032 struct spoolss_AddPort *r)
10034 /* do what w2k3 does */
10036 return WERR_NOT_SUPPORTED;
10039 /****************************************************************
10040 _spoolss_GetPrinterDriver
10041 ****************************************************************/
10043 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10044 struct spoolss_GetPrinterDriver *r)
10046 p->rng_fault_state = true;
10047 return WERR_NOT_SUPPORTED;
10050 /****************************************************************
10051 _spoolss_ReadPrinter
10052 ****************************************************************/
10054 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10055 struct spoolss_ReadPrinter *r)
10057 p->rng_fault_state = true;
10058 return WERR_NOT_SUPPORTED;
10061 /****************************************************************
10062 _spoolss_WaitForPrinterChange
10063 ****************************************************************/
10065 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10066 struct spoolss_WaitForPrinterChange *r)
10068 p->rng_fault_state = true;
10069 return WERR_NOT_SUPPORTED;
10072 /****************************************************************
10073 _spoolss_ConfigurePort
10074 ****************************************************************/
10076 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10077 struct spoolss_ConfigurePort *r)
10079 p->rng_fault_state = true;
10080 return WERR_NOT_SUPPORTED;
10083 /****************************************************************
10084 _spoolss_DeletePort
10085 ****************************************************************/
10087 WERROR _spoolss_DeletePort(pipes_struct *p,
10088 struct spoolss_DeletePort *r)
10090 p->rng_fault_state = true;
10091 return WERR_NOT_SUPPORTED;
10094 /****************************************************************
10095 _spoolss_CreatePrinterIC
10096 ****************************************************************/
10098 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10099 struct spoolss_CreatePrinterIC *r)
10101 p->rng_fault_state = true;
10102 return WERR_NOT_SUPPORTED;
10105 /****************************************************************
10106 _spoolss_PlayGDIScriptOnPrinterIC
10107 ****************************************************************/
10109 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10110 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10112 p->rng_fault_state = true;
10113 return WERR_NOT_SUPPORTED;
10116 /****************************************************************
10117 _spoolss_DeletePrinterIC
10118 ****************************************************************/
10120 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10121 struct spoolss_DeletePrinterIC *r)
10123 p->rng_fault_state = true;
10124 return WERR_NOT_SUPPORTED;
10127 /****************************************************************
10128 _spoolss_AddPrinterConnection
10129 ****************************************************************/
10131 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10132 struct spoolss_AddPrinterConnection *r)
10134 p->rng_fault_state = true;
10135 return WERR_NOT_SUPPORTED;
10138 /****************************************************************
10139 _spoolss_DeletePrinterConnection
10140 ****************************************************************/
10142 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10143 struct spoolss_DeletePrinterConnection *r)
10145 p->rng_fault_state = true;
10146 return WERR_NOT_SUPPORTED;
10149 /****************************************************************
10150 _spoolss_PrinterMessageBox
10151 ****************************************************************/
10153 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10154 struct spoolss_PrinterMessageBox *r)
10156 p->rng_fault_state = true;
10157 return WERR_NOT_SUPPORTED;
10160 /****************************************************************
10161 _spoolss_AddMonitor
10162 ****************************************************************/
10164 WERROR _spoolss_AddMonitor(pipes_struct *p,
10165 struct spoolss_AddMonitor *r)
10167 p->rng_fault_state = true;
10168 return WERR_NOT_SUPPORTED;
10171 /****************************************************************
10172 _spoolss_DeleteMonitor
10173 ****************************************************************/
10175 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10176 struct spoolss_DeleteMonitor *r)
10178 p->rng_fault_state = true;
10179 return WERR_NOT_SUPPORTED;
10182 /****************************************************************
10183 _spoolss_DeletePrintProcessor
10184 ****************************************************************/
10186 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10187 struct spoolss_DeletePrintProcessor *r)
10189 p->rng_fault_state = true;
10190 return WERR_NOT_SUPPORTED;
10193 /****************************************************************
10194 _spoolss_AddPrintProvidor
10195 ****************************************************************/
10197 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10198 struct spoolss_AddPrintProvidor *r)
10200 p->rng_fault_state = true;
10201 return WERR_NOT_SUPPORTED;
10204 /****************************************************************
10205 _spoolss_DeletePrintProvidor
10206 ****************************************************************/
10208 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10209 struct spoolss_DeletePrintProvidor *r)
10211 p->rng_fault_state = true;
10212 return WERR_NOT_SUPPORTED;
10215 /****************************************************************
10216 _spoolss_FindFirstPrinterChangeNotification
10217 ****************************************************************/
10219 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10220 struct spoolss_FindFirstPrinterChangeNotification *r)
10222 p->rng_fault_state = true;
10223 return WERR_NOT_SUPPORTED;
10226 /****************************************************************
10227 _spoolss_FindNextPrinterChangeNotification
10228 ****************************************************************/
10230 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10231 struct spoolss_FindNextPrinterChangeNotification *r)
10233 p->rng_fault_state = true;
10234 return WERR_NOT_SUPPORTED;
10237 /****************************************************************
10238 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10239 ****************************************************************/
10241 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10242 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10244 p->rng_fault_state = true;
10245 return WERR_NOT_SUPPORTED;
10248 /****************************************************************
10249 _spoolss_ReplyOpenPrinter
10250 ****************************************************************/
10252 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10253 struct spoolss_ReplyOpenPrinter *r)
10255 p->rng_fault_state = true;
10256 return WERR_NOT_SUPPORTED;
10259 /****************************************************************
10260 _spoolss_RouterReplyPrinter
10261 ****************************************************************/
10263 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10264 struct spoolss_RouterReplyPrinter *r)
10266 p->rng_fault_state = true;
10267 return WERR_NOT_SUPPORTED;
10270 /****************************************************************
10271 _spoolss_ReplyClosePrinter
10272 ****************************************************************/
10274 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10275 struct spoolss_ReplyClosePrinter *r)
10277 p->rng_fault_state = true;
10278 return WERR_NOT_SUPPORTED;
10281 /****************************************************************
10282 _spoolss_AddPortEx
10283 ****************************************************************/
10285 WERROR _spoolss_AddPortEx(pipes_struct *p,
10286 struct spoolss_AddPortEx *r)
10288 p->rng_fault_state = true;
10289 return WERR_NOT_SUPPORTED;
10292 /****************************************************************
10293 _spoolss_RouterFindFirstPrinterChangeNotification
10294 ****************************************************************/
10296 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10297 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10299 p->rng_fault_state = true;
10300 return WERR_NOT_SUPPORTED;
10303 /****************************************************************
10304 _spoolss_SpoolerInit
10305 ****************************************************************/
10307 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10308 struct spoolss_SpoolerInit *r)
10310 p->rng_fault_state = true;
10311 return WERR_NOT_SUPPORTED;
10314 /****************************************************************
10315 _spoolss_ResetPrinterEx
10316 ****************************************************************/
10318 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10319 struct spoolss_ResetPrinterEx *r)
10321 p->rng_fault_state = true;
10322 return WERR_NOT_SUPPORTED;
10325 /****************************************************************
10326 _spoolss_RouterReplyPrinterEx
10327 ****************************************************************/
10329 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10330 struct spoolss_RouterReplyPrinterEx *r)
10332 p->rng_fault_state = true;
10333 return WERR_NOT_SUPPORTED;
10336 /****************************************************************
10337 _spoolss_44
10338 ****************************************************************/
10340 WERROR _spoolss_44(pipes_struct *p,
10341 struct spoolss_44 *r)
10343 p->rng_fault_state = true;
10344 return WERR_NOT_SUPPORTED;
10347 /****************************************************************
10348 _spoolss_47
10349 ****************************************************************/
10351 WERROR _spoolss_47(pipes_struct *p,
10352 struct spoolss_47 *r)
10354 p->rng_fault_state = true;
10355 return WERR_NOT_SUPPORTED;
10358 /****************************************************************
10359 _spoolss_4a
10360 ****************************************************************/
10362 WERROR _spoolss_4a(pipes_struct *p,
10363 struct spoolss_4a *r)
10365 p->rng_fault_state = true;
10366 return WERR_NOT_SUPPORTED;
10369 /****************************************************************
10370 _spoolss_4b
10371 ****************************************************************/
10373 WERROR _spoolss_4b(pipes_struct *p,
10374 struct spoolss_4b *r)
10376 p->rng_fault_state = true;
10377 return WERR_NOT_SUPPORTED;
10380 /****************************************************************
10381 _spoolss_4c
10382 ****************************************************************/
10384 WERROR _spoolss_4c(pipes_struct *p,
10385 struct spoolss_4c *r)
10387 p->rng_fault_state = true;
10388 return WERR_NOT_SUPPORTED;
10391 /****************************************************************
10392 _spoolss_53
10393 ****************************************************************/
10395 WERROR _spoolss_53(pipes_struct *p,
10396 struct spoolss_53 *r)
10398 p->rng_fault_state = true;
10399 return WERR_NOT_SUPPORTED;
10402 /****************************************************************
10403 _spoolss_55
10404 ****************************************************************/
10406 WERROR _spoolss_55(pipes_struct *p,
10407 struct spoolss_55 *r)
10409 p->rng_fault_state = true;
10410 return WERR_NOT_SUPPORTED;
10413 /****************************************************************
10414 _spoolss_56
10415 ****************************************************************/
10417 WERROR _spoolss_56(pipes_struct *p,
10418 struct spoolss_56 *r)
10420 p->rng_fault_state = true;
10421 return WERR_NOT_SUPPORTED;
10424 /****************************************************************
10425 _spoolss_57
10426 ****************************************************************/
10428 WERROR _spoolss_57(pipes_struct *p,
10429 struct spoolss_57 *r)
10431 p->rng_fault_state = true;
10432 return WERR_NOT_SUPPORTED;
10435 /****************************************************************
10436 _spoolss_5a
10437 ****************************************************************/
10439 WERROR _spoolss_5a(pipes_struct *p,
10440 struct spoolss_5a *r)
10442 p->rng_fault_state = true;
10443 return WERR_NOT_SUPPORTED;
10446 /****************************************************************
10447 _spoolss_5b
10448 ****************************************************************/
10450 WERROR _spoolss_5b(pipes_struct *p,
10451 struct spoolss_5b *r)
10453 p->rng_fault_state = true;
10454 return WERR_NOT_SUPPORTED;
10457 /****************************************************************
10458 _spoolss_5c
10459 ****************************************************************/
10461 WERROR _spoolss_5c(pipes_struct *p,
10462 struct spoolss_5c *r)
10464 p->rng_fault_state = true;
10465 return WERR_NOT_SUPPORTED;
10468 /****************************************************************
10469 _spoolss_5d
10470 ****************************************************************/
10472 WERROR _spoolss_5d(pipes_struct *p,
10473 struct spoolss_5d *r)
10475 p->rng_fault_state = true;
10476 return WERR_NOT_SUPPORTED;
10479 /****************************************************************
10480 _spoolss_5e
10481 ****************************************************************/
10483 WERROR _spoolss_5e(pipes_struct *p,
10484 struct spoolss_5e *r)
10486 p->rng_fault_state = true;
10487 return WERR_NOT_SUPPORTED;
10490 /****************************************************************
10491 _spoolss_5f
10492 ****************************************************************/
10494 WERROR _spoolss_5f(pipes_struct *p,
10495 struct spoolss_5f *r)
10497 p->rng_fault_state = true;
10498 return WERR_NOT_SUPPORTED;
10501 /****************************************************************
10502 _spoolss_60
10503 ****************************************************************/
10505 WERROR _spoolss_60(pipes_struct *p,
10506 struct spoolss_60 *r)
10508 p->rng_fault_state = true;
10509 return WERR_NOT_SUPPORTED;
10512 /****************************************************************
10513 _spoolss_61
10514 ****************************************************************/
10516 WERROR _spoolss_61(pipes_struct *p,
10517 struct spoolss_61 *r)
10519 p->rng_fault_state = true;
10520 return WERR_NOT_SUPPORTED;
10523 /****************************************************************
10524 _spoolss_62
10525 ****************************************************************/
10527 WERROR _spoolss_62(pipes_struct *p,
10528 struct spoolss_62 *r)
10530 p->rng_fault_state = true;
10531 return WERR_NOT_SUPPORTED;
10534 /****************************************************************
10535 _spoolss_63
10536 ****************************************************************/
10538 WERROR _spoolss_63(pipes_struct *p,
10539 struct spoolss_63 *r)
10541 p->rng_fault_state = true;
10542 return WERR_NOT_SUPPORTED;
10545 /****************************************************************
10546 _spoolss_64
10547 ****************************************************************/
10549 WERROR _spoolss_64(pipes_struct *p,
10550 struct spoolss_64 *r)
10552 p->rng_fault_state = true;
10553 return WERR_NOT_SUPPORTED;
10556 /****************************************************************
10557 _spoolss_65
10558 ****************************************************************/
10560 WERROR _spoolss_65(pipes_struct *p,
10561 struct spoolss_65 *r)
10563 p->rng_fault_state = true;
10564 return WERR_NOT_SUPPORTED;
10567 /****************************************************************
10568 _spoolss_GetCorePrinterDrivers
10569 ****************************************************************/
10571 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10572 struct spoolss_GetCorePrinterDrivers *r)
10574 p->rng_fault_state = true;
10575 return WERR_NOT_SUPPORTED;
10578 /****************************************************************
10579 _spoolss_67
10580 ****************************************************************/
10582 WERROR _spoolss_67(pipes_struct *p,
10583 struct spoolss_67 *r)
10585 p->rng_fault_state = true;
10586 return WERR_NOT_SUPPORTED;
10589 /****************************************************************
10590 _spoolss_GetPrinterDriverPackagePath
10591 ****************************************************************/
10593 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10594 struct spoolss_GetPrinterDriverPackagePath *r)
10596 p->rng_fault_state = true;
10597 return WERR_NOT_SUPPORTED;
10600 /****************************************************************
10601 _spoolss_69
10602 ****************************************************************/
10604 WERROR _spoolss_69(pipes_struct *p,
10605 struct spoolss_69 *r)
10607 p->rng_fault_state = true;
10608 return WERR_NOT_SUPPORTED;
10611 /****************************************************************
10612 _spoolss_6a
10613 ****************************************************************/
10615 WERROR _spoolss_6a(pipes_struct *p,
10616 struct spoolss_6a *r)
10618 p->rng_fault_state = true;
10619 return WERR_NOT_SUPPORTED;
10622 /****************************************************************
10623 _spoolss_6b
10624 ****************************************************************/
10626 WERROR _spoolss_6b(pipes_struct *p,
10627 struct spoolss_6b *r)
10629 p->rng_fault_state = true;
10630 return WERR_NOT_SUPPORTED;
10633 /****************************************************************
10634 _spoolss_6c
10635 ****************************************************************/
10637 WERROR _spoolss_6c(pipes_struct *p,
10638 struct spoolss_6c *r)
10640 p->rng_fault_state = true;
10641 return WERR_NOT_SUPPORTED;
10644 /****************************************************************
10645 _spoolss_6d
10646 ****************************************************************/
10648 WERROR _spoolss_6d(pipes_struct *p,
10649 struct spoolss_6d *r)
10651 p->rng_fault_state = true;
10652 return WERR_NOT_SUPPORTED;