• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source3/registry/
1/*
2 *  Unix SMB/CIFS implementation.
3 *  Virtual Windows Registry Layer
4 *  Copyright (C) Gerald Carter                     2002-2005
5 *
6 *  This program is free software; you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation; either version 3 of the License, or
9 *  (at your option) any later version.
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20/* Implementation of registry virtual views for printing information */
21
22#include "includes.h"
23
24#undef DBGC_CLASS
25#define DBGC_CLASS DBGC_REGISTRY
26
27/* registrt paths used in the print_registry[] */
28
29#define KEY_MONITORS		"HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/MONITORS"
30#define KEY_FORMS		"HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/FORMS"
31#define KEY_CONTROL_PRINTERS	"HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS"
32#define KEY_ENVIRONMENTS	"HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS"
33#define KEY_CONTROL_PRINT	"HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT"
34#define KEY_WINNT_PRINTERS	"HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
35#define KEY_WINNT_PRINT		"HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT"
36#define KEY_PORTS		"HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PORTS"
37
38/* callback table for various registry paths below the ones we service in this module */
39
40struct reg_dyn_tree {
41	/* full key path in normalized form */
42	const char *path;
43
44	/* callbscks for fetch/store operations */
45	int ( *fetch_subkeys) ( const char *path, struct regsubkey_ctr *subkeys );
46	bool (*store_subkeys) ( const char *path, struct regsubkey_ctr *subkeys );
47	int  (*fetch_values)  ( const char *path, struct regval_ctr *values );
48	bool (*store_values)  ( const char *path, struct regval_ctr *values );
49};
50
51/*********************************************************************
52 *********************************************************************
53 ** Utility Functions
54 *********************************************************************
55 *********************************************************************/
56
57/***********************************************************************
58 simple function to prune a pathname down to the basename of a file
59 **********************************************************************/
60
61static const char *dos_basename(const char *path)
62{
63	const char *p;
64
65	if (!(p = strrchr( path, '\\'))) {
66		p = path;
67	} else {
68		p++;
69	}
70
71	return p;
72}
73
74/*********************************************************************
75 *********************************************************************
76 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/FORMS"
77 *********************************************************************
78 *********************************************************************/
79
80static int key_forms_fetch_keys(const char *key, struct regsubkey_ctr *subkeys)
81{
82	char *p = reg_remaining_path(talloc_tos(), key + strlen(KEY_FORMS));
83
84	/* no keys below Forms */
85
86	if (p) {
87		return -1;
88	}
89
90	return 0;
91}
92
93/**********************************************************************
94 *********************************************************************/
95
96static int key_forms_fetch_values(const char *key, struct regval_ctr *values)
97{
98	uint32 		data[8];
99	int		i, num_values, form_index = 1;
100	nt_forms_struct *forms_list = NULL;
101	nt_forms_struct *form;
102
103	DEBUG(10,("print_values_forms: key=>[%s]\n", key ? key : "NULL" ));
104
105	num_values = get_ntforms( &forms_list );
106
107	DEBUG(10,("hive_forms_fetch_values: [%d] user defined forms returned\n",
108		num_values));
109
110	/* handle user defined forms */
111
112	for ( i=0; i<num_values; i++ ) {
113		form = &forms_list[i];
114
115		data[0] = form->width;
116		data[1] = form->length;
117		data[2] = form->left;
118		data[3] = form->top;
119		data[4] = form->right;
120		data[5] = form->bottom;
121		data[6] = form_index++;
122		data[7] = form->flag;
123
124		regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );
125	}
126
127	SAFE_FREE( forms_list );
128	forms_list = NULL;
129
130	/* handle built-on forms */
131
132	num_values = get_builtin_ntforms( &forms_list );
133
134	DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n",
135		num_values));
136
137	for ( i=0; i<num_values; i++ ) {
138		form = &forms_list[i];
139
140		data[0] = form->width;
141		data[1] = form->length;
142		data[2] = form->left;
143		data[3] = form->top;
144		data[4] = form->right;
145		data[5] = form->bottom;
146		data[6] = form_index++;
147		data[7] = form->flag;
148
149		regval_ctr_addvalue(values, form->name, REG_BINARY, (char*)data, sizeof(data) );
150	}
151
152	SAFE_FREE(forms_list);
153
154	return regval_ctr_numvals(values);
155}
156
157/*********************************************************************
158 *********************************************************************
159 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS"
160 ** "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
161 *********************************************************************
162 *********************************************************************/
163
164/*********************************************************************
165 strip off prefix for printers key.  DOes return a pointer to static
166 memory.
167 *********************************************************************/
168
169static char *strip_printers_prefix(const char *key)
170{
171	char *subkeypath = NULL;
172	char *path = NULL;
173	TALLOC_CTX *ctx = talloc_tos();
174
175	path = talloc_strdup(ctx, key);
176	if (!path) {
177		return NULL;
178	}
179	path = normalize_reg_path(ctx, path);
180	if (!path) {
181		return NULL;
182	}
183
184	/* normalizing the path does not change length, just key delimiters and case */
185
186	if (strncmp(path, KEY_WINNT_PRINTERS, strlen(KEY_WINNT_PRINTERS)) == 0) {
187		subkeypath = reg_remaining_path(ctx, key + strlen(KEY_WINNT_PRINTERS));
188	} else {
189		subkeypath = reg_remaining_path(ctx, key + strlen(KEY_CONTROL_PRINTERS));
190	}
191
192	TALLOC_FREE(path);
193	return subkeypath;
194}
195
196/*********************************************************************
197 *********************************************************************/
198
199static int key_printers_fetch_keys( const char *key, struct regsubkey_ctr *subkeys )
200{
201	int n_services = lp_numservices();
202	int snum;
203	fstring sname;
204	int i;
205	int num_subkeys = 0;
206	char *printers_key;
207	char *printername, *printerdatakey;
208	NT_PRINTER_INFO_LEVEL *printer = NULL;
209	fstring *subkey_names = NULL;
210
211	DEBUG(10,("key_printers_fetch_keys: key=>[%s]\n", key ? key : "NULL" ));
212
213	printers_key = strip_printers_prefix( key );
214
215	if ( !printers_key ) {
216		/* enumerate all printers */
217
218		for (snum=0; snum<n_services; snum++) {
219			if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
220				continue;
221
222			/* don't report the [printers] share */
223
224			if ( strequal( lp_servicename(snum), PRINTERS_NAME ) )
225				continue;
226
227			fstrcpy( sname, lp_servicename(snum) );
228
229			regsubkey_ctr_addkey( subkeys, sname );
230		}
231
232		num_subkeys = regsubkey_ctr_numkeys( subkeys );
233		goto done;
234	}
235
236	/* get information for a specific printer */
237
238	if (!reg_split_path( printers_key, &printername, &printerdatakey )) {
239		return -1;
240	}
241
242	/* validate the printer name */
243
244	for (snum=0; snum<n_services; snum++) {
245		if ( !lp_snum_ok(snum) || !lp_print_ok(snum) )
246			continue;
247		if (strequal( lp_servicename(snum), printername ) )
248			break;
249	}
250
251	if ( snum>=n_services
252		|| !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
253	{
254		return -1;
255	}
256
257	num_subkeys = get_printer_subkeys( printer->info_2->data, printerdatakey?printerdatakey:"", &subkey_names );
258
259	for ( i=0; i<num_subkeys; i++ )
260		regsubkey_ctr_addkey( subkeys, subkey_names[i] );
261
262	free_a_printer( &printer, 2 );
263
264	/* no other subkeys below here */
265
266done:
267	SAFE_FREE( subkey_names );
268
269	return num_subkeys;
270}
271
272/**********************************************************************
273 Take a list of names and call add_printer_hook() if necessary
274 Note that we do this a little differently from Windows since the
275 keyname is the sharename and not the printer name.
276 *********************************************************************/
277
278static bool add_printers_by_registry( struct regsubkey_ctr *subkeys )
279{
280	int i, num_keys, snum;
281	char *printername;
282	NT_PRINTER_INFO_LEVEL_2 info2;
283	NT_PRINTER_INFO_LEVEL printer;
284
285	ZERO_STRUCT( info2 );
286	printer.info_2 = &info2;
287
288	num_keys = regsubkey_ctr_numkeys( subkeys );
289
290	become_root();
291	for ( i=0; i<num_keys; i++ ) {
292		printername = regsubkey_ctr_specific_key( subkeys, i );
293		snum = find_service( printername );
294
295		/* just verify a valied snum for now */
296		if ( snum == -1 ) {
297			fstrcpy( info2.printername, printername );
298			fstrcpy( info2.sharename, printername );
299			if ( !add_printer_hook(talloc_tos(), NULL, &printer ) ) {
300				DEBUG(0,("add_printers_by_registry: Failed to add printer [%s]\n",
301					printername));
302			}
303		}
304	}
305	unbecome_root();
306
307	return True;
308}
309
310/**********************************************************************
311 *********************************************************************/
312
313static bool key_printers_store_keys( const char *key, struct regsubkey_ctr *subkeys )
314{
315	char *printers_key;
316	char *printername, *printerdatakey;
317	NT_PRINTER_INFO_LEVEL *printer = NULL;
318	int i, num_subkeys, num_existing_keys;
319	char *subkeyname;
320	fstring *existing_subkeys = NULL;
321
322	printers_key = strip_printers_prefix( key );
323
324	if ( !printers_key ) {
325		/* have to deal with some new or deleted printer */
326		return add_printers_by_registry( subkeys );
327	}
328
329	if (!reg_split_path( printers_key, &printername, &printerdatakey )) {
330		return False;
331	}
332
333	/* lookup the printer */
334
335	if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, printername)) ) {
336		DEBUG(0,("key_printers_store_keys: Tried to store subkey for bad printername %s\n",
337			printername));
338		return False;
339	}
340
341	/* get the top level printer keys */
342
343	num_existing_keys = get_printer_subkeys( printer->info_2->data, "", &existing_subkeys );
344
345	for ( i=0; i<num_existing_keys; i++ ) {
346
347		/* remove the key if it has been deleted */
348
349		if ( !regsubkey_ctr_key_exists( subkeys, existing_subkeys[i] ) ) {
350			DEBUG(5,("key_printers_store_keys: deleting key %s\n",
351				existing_subkeys[i]));
352			delete_printer_key( printer->info_2->data, existing_subkeys[i] );
353		}
354	}
355
356	num_subkeys = regsubkey_ctr_numkeys( subkeys );
357	for ( i=0; i<num_subkeys; i++ ) {
358		subkeyname = regsubkey_ctr_specific_key(subkeys, i);
359		/* add any missing printer keys */
360		if ( lookup_printerkey(printer->info_2->data, subkeyname) == -1 ) {
361			DEBUG(5,("key_printers_store_keys: adding key %s\n",
362				existing_subkeys[i]));
363			if ( add_new_printer_key( printer->info_2->data, subkeyname ) == -1 ) {
364				SAFE_FREE( existing_subkeys );
365				return False;
366			}
367		}
368	}
369
370	/* write back to disk */
371
372	mod_a_printer( printer, 2 );
373
374	/* cleanup */
375
376	free_a_printer( &printer, 2 );
377
378	SAFE_FREE( existing_subkeys );
379
380	return True;
381}
382
383/**********************************************************************
384 *********************************************************************/
385
386static void fill_in_printer_values(NT_PRINTER_INFO_LEVEL_2 *info2, struct regval_ctr *values)
387{
388	struct spoolss_DeviceMode *devmode;
389	char 		*p;
390	uint32 printer_status = PRINTER_STATUS_OK;
391
392	regval_ctr_addvalue( values, "Attributes",       REG_DWORD, (char*)&info2->attributes,       sizeof(info2->attributes) );
393	regval_ctr_addvalue( values, "Priority",         REG_DWORD, (char*)&info2->priority,         sizeof(info2->attributes) );
394	regval_ctr_addvalue( values, "ChangeID",         REG_DWORD, (char*)&info2->changeid,         sizeof(info2->changeid) );
395	regval_ctr_addvalue( values, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) );
396
397	/* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */
398	regval_ctr_addvalue( values, "Status",           REG_DWORD, (char*)&printer_status,          sizeof(info2->status) );
399
400	regval_ctr_addvalue( values, "StartTime",        REG_DWORD, (char*)&info2->starttime,        sizeof(info2->starttime) );
401	regval_ctr_addvalue( values, "UntilTime",        REG_DWORD, (char*)&info2->untiltime,        sizeof(info2->untiltime) );
402
403	/* strip the \\server\ from this string */
404	if ( !(p = strrchr( info2->printername, '\\' ) ) )
405		p = info2->printername;
406	else
407		p++;
408
409	regval_ctr_addvalue_sz(values, "Name", p);
410	regval_ctr_addvalue_sz(values, "Location", info2->location);
411	regval_ctr_addvalue_sz(values, "Description", info2->comment);
412	regval_ctr_addvalue_sz(values, "Parameters", info2->parameters);
413	regval_ctr_addvalue_sz(values, "Port", info2->portname);
414	regval_ctr_addvalue_sz(values, "Share Name", info2->sharename);
415	regval_ctr_addvalue_sz(values, "Printer Driver", info2->drivername);
416	regval_ctr_addvalue_sz(values, "Separator File", info2->sepfile);
417	regval_ctr_addvalue_sz(values, "Print Processor", "WinPrint");
418	regval_ctr_addvalue_sz(values, "Datatype", "RAW");
419
420	/* stream the device mode */
421
422	devmode = construct_dev_mode(values,info2->sharename);
423	if (devmode) {
424		DATA_BLOB blob;
425		enum ndr_err_code ndr_err;
426
427		ndr_err = ndr_push_struct_blob(&blob, values, NULL, devmode,
428				(ndr_push_flags_fn_t)ndr_push_spoolss_DeviceMode);
429
430		if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
431			regval_ctr_addvalue(values, "Default Devmode", REG_BINARY,
432					    (const char *)blob.data, blob.length);
433		}
434	}
435
436	/* stream the printer security descriptor */
437
438	if (info2->secdesc_buf &&
439	    info2->secdesc_buf->sd &&
440	    info2->secdesc_buf->sd_size)
441	{
442		NTSTATUS status;
443		DATA_BLOB blob;
444
445		status = marshall_sec_desc(values, info2->secdesc_buf->sd,
446					   &blob.data, &blob.length);
447		if (NT_STATUS_IS_OK(status)) {
448			regval_ctr_addvalue(values, "Security", REG_BINARY,
449					    (const char *)blob.data, blob.length);
450		}
451	}
452
453	return;
454}
455
456/**********************************************************************
457 *********************************************************************/
458
459static int key_printers_fetch_values(const char *key, struct regval_ctr *values)
460{
461	int 		num_values;
462	char		*printers_key;
463	char		*printername, *printerdatakey;
464	NT_PRINTER_INFO_LEVEL 	*printer = NULL;
465	NT_PRINTER_DATA	*p_data;
466	int		i, key_index;
467
468	printers_key = strip_printers_prefix( key );
469
470	/* top level key values stored in the registry has no values */
471
472	if ( !printers_key ) {
473		/* normalize to the 'HKLM\SOFTWARE\...\Print\Printers' key */
474		return regdb_fetch_values( KEY_WINNT_PRINTERS, values );
475	}
476
477	/* lookup the printer object */
478
479	if (!reg_split_path( printers_key, &printername, &printerdatakey )) {
480		return -1;
481	}
482
483	if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
484		goto done;
485
486	if ( !printerdatakey ) {
487		fill_in_printer_values( printer->info_2, values );
488		goto done;
489	}
490
491	/* iterate over all printer data keys and fill the regval container */
492
493	p_data = printer->info_2->data;
494	if ( (key_index = lookup_printerkey( p_data, printerdatakey )) == -1  ) {
495		/* failure....should never happen if the client has a valid open handle first */
496		DEBUG(10,("key_printers_fetch_values: Unknown keyname [%s]\n", printerdatakey));
497		free_a_printer( &printer, 2 );
498		return -1;
499	}
500
501	num_values = regval_ctr_numvals( p_data->keys[key_index].values );
502	for ( i=0; i<num_values; i++ )
503		regval_ctr_copyvalue( values, regval_ctr_specific_value(p_data->keys[key_index].values, i) );
504
505
506done:
507	if ( printer )
508		free_a_printer( &printer, 2 );
509
510	return regval_ctr_numvals( values );
511}
512
513/**********************************************************************
514 *********************************************************************/
515
516#define REG_IDX_ATTRIBUTES		1
517#define REG_IDX_PRIORITY		2
518#define REG_IDX_DEFAULT_PRIORITY	3
519#define REG_IDX_CHANGEID		4
520#define REG_IDX_STATUS			5
521#define REG_IDX_STARTTIME		6
522#define REG_IDX_NAME			7
523#define REG_IDX_LOCATION		8
524#define REG_IDX_DESCRIPTION		9
525#define REG_IDX_PARAMETERS		10
526#define REG_IDX_PORT			12
527#define REG_IDX_SHARENAME		13
528#define REG_IDX_DRIVER			14
529#define REG_IDX_SEP_FILE		15
530#define REG_IDX_PRINTPROC		16
531#define REG_IDX_DATATYPE		17
532#define REG_IDX_DEVMODE			18
533#define REG_IDX_SECDESC			19
534#define REG_IDX_UNTILTIME		20
535
536struct {
537	const char *name;
538	int index;
539} printer_values_map[] = {
540	{ "Attributes", 	REG_IDX_ATTRIBUTES },
541	{ "Priority", 		REG_IDX_PRIORITY },
542	{ "Default Priority", 	REG_IDX_DEFAULT_PRIORITY },
543	{ "ChangeID", 		REG_IDX_CHANGEID },
544	{ "Status", 		REG_IDX_STATUS },
545	{ "StartTime", 		REG_IDX_STARTTIME },
546	{ "UntilTime",	 	REG_IDX_UNTILTIME },
547	{ "Name", 		REG_IDX_NAME },
548	{ "Location", 		REG_IDX_LOCATION },
549	{ "Description", 	REG_IDX_DESCRIPTION },
550	{ "Parameters", 	REG_IDX_PARAMETERS },
551	{ "Port", 		REG_IDX_PORT },
552	{ "Share Name", 	REG_IDX_SHARENAME },
553	{ "Printer Driver", 	REG_IDX_DRIVER },
554	{ "Separator File", 	REG_IDX_SEP_FILE },
555	{ "Print Processor", 	REG_IDX_PRINTPROC },
556	{ "Datatype", 		REG_IDX_DATATYPE },
557	{ "Default Devmode", 	REG_IDX_DEVMODE },
558	{ "Security", 		REG_IDX_SECDESC },
559	{ NULL, -1 }
560};
561
562
563static int find_valuename_index( const char *valuename )
564{
565	int i;
566
567	for ( i=0; printer_values_map[i].name; i++ ) {
568		if ( strequal( valuename, printer_values_map[i].name ) )
569			return printer_values_map[i].index;
570	}
571
572	return -1;
573}
574
575/**********************************************************************
576 *********************************************************************/
577
578static void pull_reg_sz_fstring(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, fstring s)
579{
580	const char *str;
581	pull_reg_sz(mem_ctx, blob, &str);
582	fstrcpy(s, str);
583}
584
585static void convert_values_to_printer_info_2(TALLOC_CTX *mem_ctx,
586					     NT_PRINTER_INFO_LEVEL_2 *printer2,
587					     struct regval_ctr *values)
588{
589	int num_values = regval_ctr_numvals( values );
590	uint32 value_index;
591	struct regval_blob *val;
592	int i;
593
594	for ( i=0; i<num_values; i++ ) {
595		DATA_BLOB blob;
596		val = regval_ctr_specific_value( values, i );
597		value_index = find_valuename_index( regval_name( val ) );
598
599		blob = data_blob_const(regval_data_p(val), regval_size(val));
600
601		switch( value_index ) {
602			case REG_IDX_ATTRIBUTES:
603				printer2->attributes = (uint32)(*regval_data_p(val));
604				break;
605			case REG_IDX_PRIORITY:
606				printer2->priority = (uint32)(*regval_data_p(val));
607				break;
608			case REG_IDX_DEFAULT_PRIORITY:
609				printer2->default_priority = (uint32)(*regval_data_p(val));
610				break;
611			case REG_IDX_CHANGEID:
612				printer2->changeid = (uint32)(*regval_data_p(val));
613				break;
614			case REG_IDX_STARTTIME:
615				printer2->starttime = (uint32)(*regval_data_p(val));
616				break;
617			case REG_IDX_UNTILTIME:
618				printer2->untiltime = (uint32)(*regval_data_p(val));
619				break;
620			case REG_IDX_NAME:
621				pull_reg_sz_fstring(mem_ctx, &blob, printer2->printername);
622				break;
623			case REG_IDX_LOCATION:
624				pull_reg_sz_fstring(mem_ctx, &blob, printer2->location);
625				break;
626			case REG_IDX_DESCRIPTION:
627				pull_reg_sz_fstring(mem_ctx, &blob, printer2->comment);
628				break;
629			case REG_IDX_PARAMETERS:
630				pull_reg_sz_fstring(mem_ctx, &blob, printer2->parameters);
631				break;
632			case REG_IDX_PORT:
633				pull_reg_sz_fstring(mem_ctx, &blob, printer2->portname);
634				break;
635			case REG_IDX_SHARENAME:
636				pull_reg_sz_fstring(mem_ctx, &blob, printer2->sharename);
637				break;
638			case REG_IDX_DRIVER:
639				pull_reg_sz_fstring(mem_ctx, &blob, printer2->drivername);
640				break;
641			case REG_IDX_SEP_FILE:
642				pull_reg_sz_fstring(mem_ctx, &blob, printer2->sepfile);
643				break;
644			case REG_IDX_PRINTPROC:
645				pull_reg_sz_fstring(mem_ctx, &blob, printer2->printprocessor);
646				break;
647			case REG_IDX_DATATYPE:
648				pull_reg_sz_fstring(mem_ctx, &blob, printer2->datatype);
649				break;
650			case REG_IDX_DEVMODE:
651				break;
652			case REG_IDX_SECDESC:
653				break;
654			default:
655				/* unsupported value...throw away */
656				DEBUG(8,("convert_values_to_printer_info_2: Unsupported registry value [%s]\n",
657					regval_name( val ) ));
658		}
659	}
660
661	return;
662}
663
664/**********************************************************************
665 *********************************************************************/
666
667static bool key_printers_store_values(const char *key, struct regval_ctr *values)
668{
669	char *printers_key;
670	char *printername, *keyname;
671	NT_PRINTER_INFO_LEVEL   *printer = NULL;
672	WERROR result;
673	TALLOC_CTX *mem_ctx = talloc_init("key_printers_store_values");
674
675	printers_key = strip_printers_prefix( key );
676
677	/* values in the top level key get stored in the registry */
678
679	if ( !printers_key ) {
680		/* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
681		return regdb_store_values( KEY_WINNT_PRINTERS, values );
682	}
683
684	if (!reg_split_path( printers_key, &printername, &keyname )) {
685		return False;
686	}
687
688	if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, printername) ) )
689		return False;
690
691	/* deal with setting values directly under the printername */
692
693	if ( !keyname ) {
694		convert_values_to_printer_info_2(mem_ctx, printer->info_2, values );
695	}
696	else {
697		int num_values = regval_ctr_numvals( values );
698		int i;
699		struct regval_blob *val;
700
701		delete_printer_key( printer->info_2->data, keyname );
702
703		/* deal with any subkeys */
704		for ( i=0; i<num_values; i++ ) {
705			val = regval_ctr_specific_value( values, i );
706			result = set_printer_dataex( printer, keyname,
707				regval_name( val ),
708				regval_type( val ),
709				regval_data_p( val ),
710				regval_size( val ) );
711			if ( !W_ERROR_IS_OK(result) ) {
712				DEBUG(0,("key_printers_store_values: failed to set printer data [%s]!\n",
713					keyname));
714				free_a_printer( &printer, 2 );
715				talloc_destroy(mem_ctx);
716				return False;
717			}
718		}
719	}
720
721	result = mod_a_printer( printer, 2 );
722
723	free_a_printer( &printer, 2 );
724	talloc_destroy(mem_ctx);
725
726	return W_ERROR_IS_OK(result);
727}
728
729/*********************************************************************
730 *********************************************************************
731 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS"
732 *********************************************************************
733 *********************************************************************/
734
735static int key_driver_fetch_keys( const char *key, struct regsubkey_ctr *subkeys )
736{
737	const char *environments[] = {
738		"Windows 4.0",
739		"Windows NT x86",
740		"Windows NT R4000",
741		"Windows NT Alpha_AXP",
742		"Windows NT PowerPC",
743		"Windows IA64",
744		"Windows x64",
745		NULL };
746	fstring *drivers = NULL;
747	int i, env_index, num_drivers;
748	char *keystr, *base, *subkeypath;
749	char *key2 = NULL;
750	int num_subkeys = -1;
751	int version;
752	TALLOC_CTX *ctx = talloc_tos();
753
754	DEBUG(10,("key_driver_fetch_keys key=>[%s]\n", key ? key : "NULL" ));
755
756	keystr = reg_remaining_path(ctx, key + strlen(KEY_ENVIRONMENTS) );
757
758	/* list all possible architectures */
759
760	if ( !keystr ) {
761		for ( num_subkeys=0; environments[num_subkeys]; num_subkeys++ )
762			regsubkey_ctr_addkey( subkeys, 	environments[num_subkeys] );
763
764		return num_subkeys;
765	}
766
767	/* we are dealing with a subkey of "Environments */
768	key2 = talloc_strdup(ctx, keystr);
769	if (!key2) {
770		return -1;
771	}
772	keystr = key2;
773	if (!reg_split_path(keystr, &base, &subkeypath )) {
774		return -1;
775	}
776
777	/* sanity check */
778
779	for ( env_index=0; environments[env_index]; env_index++ ) {
780		if ( strequal( environments[env_index], base ) )
781			break;
782	}
783	if ( !environments[env_index] )
784		return -1;
785
786	/* ...\Print\Environements\...\ */
787
788	if ( !subkeypath ) {
789		regsubkey_ctr_addkey( subkeys, "Drivers" );
790		regsubkey_ctr_addkey( subkeys, "Print Processors" );
791
792		return 2;
793	}
794
795	/* more of the key path to process */
796
797	keystr = subkeypath;
798	if (!reg_split_path( keystr, &base, &subkeypath )) {
799		return -1;
800	}
801
802	/* ...\Print\Environements\...\Drivers\ */
803
804	if ( !subkeypath ) {
805		if ( strequal(base, "Drivers") ) {
806			switch ( env_index ) {
807				case 0:	/* Win9x */
808					regsubkey_ctr_addkey( subkeys, "Version-0" );
809					break;
810				default: /* Windows NT based systems */
811					regsubkey_ctr_addkey( subkeys, "Version-2" );
812					regsubkey_ctr_addkey( subkeys, "Version-3" );
813					break;
814			}
815
816			return regsubkey_ctr_numkeys( subkeys );
817		} else if ( strequal(base, "Print Processors") ) {
818			if ( env_index == 1 || env_index == 5 || env_index == 6 )
819
820
821			return regsubkey_ctr_numkeys( subkeys );
822		} else
823			return -1;	/* bad path */
824	}
825
826	/* we finally get to enumerate the drivers */
827
828	/* only one possible subkey below PrintProc key */
829
830	if ( strequal(base, "Print Processors") ) {
831		keystr = subkeypath;
832		if (!reg_split_path( keystr, &base, &subkeypath )) {
833			return -1;
834		}
835
836		/* no subkeys below this point */
837
838		if ( subkeypath )
839			return -1;
840
841		/* only allow one keyname here -- 'winprint' */
842
843		return strequal( base, "winprint" ) ? 0 : -1;
844	}
845
846	/* only dealing with drivers from here on out */
847
848	keystr = subkeypath;
849	if (!reg_split_path( keystr, &base, &subkeypath )) {
850		return -1;
851	}
852
853	version = atoi(&base[strlen(base)-1]);
854
855	switch (env_index) {
856	case 0:
857		if ( version != 0 )
858			return -1;
859		break;
860	default:
861		if ( version != 2 && version != 3 )
862			return -1;
863		break;
864	}
865
866
867	if ( !subkeypath ) {
868		num_drivers = get_ntdrivers( &drivers, environments[env_index], version );
869		for ( i=0; i<num_drivers; i++ )
870			regsubkey_ctr_addkey( subkeys, drivers[i] );
871
872		return regsubkey_ctr_numkeys( subkeys );
873	}
874
875	/* if anything else left, just say if has no subkeys */
876
877	DEBUG(1,("key_driver_fetch_keys unhandled key [%s] (subkey == %s)\n",
878		key, subkeypath ));
879
880	return 0;
881}
882
883
884/**********************************************************************
885 *********************************************************************/
886
887static void fill_in_driver_values(const struct spoolss_DriverInfo8 *r,
888				  struct regval_ctr *values)
889{
890	char *buffer = NULL;
891	int buffer_size = 0;
892	int i, length;
893	const char *filename;
894	DATA_BLOB data;
895
896	filename = dos_basename(r->driver_path);
897	regval_ctr_addvalue_sz(values, "Driver", filename);
898
899	filename = dos_basename(r->config_file);
900	regval_ctr_addvalue_sz(values, "Configuration File", filename);
901
902	filename = dos_basename(r->data_file);
903	regval_ctr_addvalue_sz(values, "Data File", filename);
904
905	filename = dos_basename(r->help_file);
906	regval_ctr_addvalue_sz(values, "Help File", filename);
907
908	regval_ctr_addvalue_sz(values, "Data Type", r->default_datatype);
909
910	regval_ctr_addvalue( values, "Version", REG_DWORD, (char*)&r->version,
911		sizeof(r->version) );
912
913	if (r->dependent_files) {
914		/* place the list of dependent files in a single
915		   character buffer, separating each file name by
916		   a NULL */
917
918		for (i=0; r->dependent_files[i] && strcmp(r->dependent_files[i], ""); i++) {
919			/* strip the path to only the file's base name */
920
921			filename = dos_basename(r->dependent_files[i]);
922
923			length = strlen(filename);
924
925			buffer = (char *)SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
926			if ( !buffer ) {
927				break;
928			}
929
930			push_reg_sz(talloc_tos(), &data, filename);
931			memcpy( buffer+buffer_size, (char*)data.data, data.length);
932
933			buffer_size += (length + 1)*sizeof(uint16);
934		}
935
936		/* terminated by double NULL.  Add the final one here */
937
938		buffer = (char *)SMB_REALLOC( buffer, buffer_size + 2 );
939		if ( !buffer ) {
940			buffer_size = 0;
941		} else {
942			buffer[buffer_size++] = '\0';
943			buffer[buffer_size++] = '\0';
944		}
945	}
946
947	regval_ctr_addvalue( values, "Dependent Files",    REG_MULTI_SZ, buffer, buffer_size );
948
949	SAFE_FREE( buffer );
950
951	return;
952}
953
954/**********************************************************************
955 *********************************************************************/
956
957static int driver_arch_fetch_values(char *key, struct regval_ctr *values)
958{
959	char 		*keystr, *base, *subkeypath;
960	fstring		arch_environment;
961	fstring		driver;
962	int		version;
963	struct spoolss_DriverInfo8 *driver_ctr;
964	WERROR		w_result;
965
966	if (!reg_split_path( key, &base, &subkeypath )) {
967		return -1;
968	}
969
970	/* no values in 'Environments\Drivers\Windows NT x86' */
971
972	if ( !subkeypath )
973		return 0;
974
975	/* We have the Architecture string and some subkey name:
976	   Currently we only support
977	   * Drivers
978	   * Print Processors
979	   Anything else is an error.
980	   */
981
982	fstrcpy( arch_environment, base );
983
984	keystr = subkeypath;
985	if (!reg_split_path( keystr, &base, &subkeypath )) {
986		return -1;
987	}
988
989	if ( strequal(base, "Print Processors") )
990		return 0;
991
992	/* only Drivers key can be left */
993
994	if ( !strequal(base, "Drivers") )
995		return -1;
996
997	if ( !subkeypath )
998		return 0;
999
1000	/* We know that we have Architechure\Drivers with some subkey name
1001	   The subkey name has to be Version-XX */
1002
1003	keystr = subkeypath;
1004	if (!reg_split_path( keystr, &base, &subkeypath )) {
1005		return -1;
1006	}
1007
1008	if ( !subkeypath )
1009		return 0;
1010
1011	version = atoi(&base[strlen(base)-1]);
1012
1013	/* BEGIN PRINTER DRIVER NAME BLOCK */
1014
1015	keystr = subkeypath;
1016	if (!reg_split_path( keystr, &base, &subkeypath )) {
1017		return -1;
1018	}
1019
1020	/* don't go any deeper for now */
1021
1022	fstrcpy( driver, base );
1023
1024	w_result = get_a_printer_driver(talloc_tos(), &driver_ctr, driver, arch_environment, version);
1025
1026	if ( !W_ERROR_IS_OK(w_result) )
1027		return -1;
1028
1029	fill_in_driver_values(driver_ctr, values);
1030
1031	free_a_printer_driver(driver_ctr);
1032
1033	/* END PRINTER DRIVER NAME BLOCK */
1034
1035
1036	DEBUG(8,("key_driver_fetch_values: Exit\n"));
1037
1038	return regval_ctr_numvals( values );
1039}
1040
1041/**********************************************************************
1042 *********************************************************************/
1043
1044static int key_driver_fetch_values(const char *key, struct regval_ctr *values)
1045{
1046	char *keystr = NULL;
1047	char *subkey = NULL;
1048	TALLOC_CTX *ctx = talloc_tos();
1049
1050	DEBUG(8,("key_driver_fetch_values: Enter key => [%s]\n", key ? key : "NULL"));
1051
1052	/* no values in the Environments key */
1053
1054	if (!(keystr = reg_remaining_path(ctx, key + strlen(KEY_ENVIRONMENTS))))
1055		return 0;
1056
1057	subkey = talloc_strdup(ctx, keystr);
1058	if (!subkey) {
1059		return 0;
1060	}
1061
1062	/* pass off to handle subkeys */
1063
1064	return driver_arch_fetch_values( subkey, values );
1065}
1066
1067/*********************************************************************
1068 *********************************************************************
1069 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT"
1070 *********************************************************************
1071 *********************************************************************/
1072
1073static int key_print_fetch_keys( const char *key, struct regsubkey_ctr *subkeys )
1074{
1075	int key_len = strlen(key);
1076
1077	/* no keys below 'Print' handled here */
1078
1079	if ( (key_len != strlen(KEY_CONTROL_PRINT)) && (key_len != strlen(KEY_WINNT_PRINT)) )
1080		return -1;
1081
1082	regsubkey_ctr_addkey( subkeys, "Environments" );
1083	regsubkey_ctr_addkey( subkeys, "Monitors" );
1084	regsubkey_ctr_addkey( subkeys, "Forms" );
1085	regsubkey_ctr_addkey( subkeys, "Printers" );
1086
1087	return regsubkey_ctr_numkeys( subkeys );
1088}
1089
1090/**********************************************************************
1091 *********************************************************************
1092 ** Structure to hold dispatch table of ops for various printer keys.
1093 ** Make sure to always store deeper keys along the same path first so
1094 ** we ge a more specific match.
1095 *********************************************************************
1096 *********************************************************************/
1097
1098static struct reg_dyn_tree print_registry[] = {
1099/* just pass the monitor onto the registry tdb */
1100{ KEY_MONITORS,
1101	&regdb_fetch_keys,
1102	&regdb_store_keys,
1103	&regdb_fetch_values,
1104	&regdb_store_values },
1105{ KEY_FORMS,
1106	&key_forms_fetch_keys,
1107	NULL,
1108	&key_forms_fetch_values,
1109	NULL },
1110{ KEY_CONTROL_PRINTERS,
1111	&key_printers_fetch_keys,
1112	&key_printers_store_keys,
1113	&key_printers_fetch_values,
1114	&key_printers_store_values },
1115{ KEY_ENVIRONMENTS,
1116	&key_driver_fetch_keys,
1117	NULL,
1118	&key_driver_fetch_values,
1119	NULL },
1120{ KEY_CONTROL_PRINT,
1121	&key_print_fetch_keys,
1122	NULL,
1123	NULL,
1124	NULL },
1125{ KEY_WINNT_PRINTERS,
1126	&key_printers_fetch_keys,
1127	&key_printers_store_keys,
1128	&key_printers_fetch_values,
1129	&key_printers_store_values },
1130{ KEY_PORTS,
1131	&regdb_fetch_keys,
1132	&regdb_store_keys,
1133	&regdb_fetch_values,
1134	&regdb_store_values },
1135
1136{ NULL, NULL, NULL, NULL, NULL }
1137};
1138
1139
1140/**********************************************************************
1141 *********************************************************************
1142 ** Main reg_printing interface functions
1143 *********************************************************************
1144 *********************************************************************/
1145
1146/***********************************************************************
1147 Lookup a key in the print_registry table, returning its index.
1148 -1 on failure
1149 **********************************************************************/
1150
1151static int match_registry_path(const char *key)
1152{
1153	int i;
1154	char *path = NULL;
1155	TALLOC_CTX *ctx = talloc_tos();
1156
1157	if ( !key )
1158		return -1;
1159
1160	path = talloc_strdup(ctx, key);
1161	if (!path) {
1162		return -1;
1163	}
1164	path = normalize_reg_path(ctx, path);
1165	if (!path) {
1166		return -1;
1167	}
1168
1169	for ( i=0; print_registry[i].path; i++ ) {
1170		if (strncmp( path, print_registry[i].path, strlen(print_registry[i].path) ) == 0 )
1171			return i;
1172	}
1173
1174	return -1;
1175}
1176
1177/***********************************************************************
1178 **********************************************************************/
1179
1180static int regprint_fetch_reg_keys( const char *key, struct regsubkey_ctr *subkeys )
1181{
1182	int i = match_registry_path( key );
1183
1184	if ( i == -1 )
1185		return -1;
1186
1187	if ( !print_registry[i].fetch_subkeys )
1188		return -1;
1189
1190	return print_registry[i].fetch_subkeys( key, subkeys );
1191}
1192
1193/**********************************************************************
1194 *********************************************************************/
1195
1196static bool regprint_store_reg_keys( const char *key, struct regsubkey_ctr *subkeys )
1197{
1198	int i = match_registry_path( key );
1199
1200	if ( i == -1 )
1201		return False;
1202
1203	if ( !print_registry[i].store_subkeys )
1204		return False;
1205
1206	return print_registry[i].store_subkeys( key, subkeys );
1207}
1208
1209/**********************************************************************
1210 *********************************************************************/
1211
1212static int regprint_fetch_reg_values(const char *key, struct regval_ctr *values)
1213{
1214	int i = match_registry_path( key );
1215
1216	if ( i == -1 )
1217		return -1;
1218
1219	/* return 0 values by default since we know the key had
1220	   to exist because the client opened a handle */
1221
1222	if ( !print_registry[i].fetch_values )
1223		return 0;
1224
1225	return print_registry[i].fetch_values( key, values );
1226}
1227
1228/**********************************************************************
1229 *********************************************************************/
1230
1231static bool regprint_store_reg_values(const char *key, struct regval_ctr *values)
1232{
1233	int i = match_registry_path( key );
1234
1235	if ( i == -1 )
1236		return False;
1237
1238	if ( !print_registry[i].store_values )
1239		return False;
1240
1241	return print_registry[i].store_values( key, values );
1242}
1243
1244/*
1245 * Table of function pointers for accessing printing data
1246 */
1247
1248struct registry_ops printing_ops = {
1249	.fetch_subkeys = regprint_fetch_reg_keys,
1250	.fetch_values = regprint_fetch_reg_values,
1251	.store_subkeys = regprint_store_reg_keys,
1252	.store_values = regprint_store_reg_values,
1253};
1254