r8027: driver information is now back via winreg
[Samba/gbeck.git] / source / registry / reg_printing.c
blob262affb4f56d57ded29cb3638f57eb24ce116167
1 /*
2 * Unix SMB/CIFS implementation.
3 * Virtual Windows Registry Layer
4 * Copyright (C) Gerald Carter 2002-2005
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 2 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /* Implementation of registry virtual views for printing information */
23 #include "includes.h"
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
28 /* registrt paths used in the print_registry[] */
30 #define KEY_MONITORS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/MONITORS"
31 #define KEY_FORMS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/FORMS"
32 #define KEY_CONTROL_PRINTERS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS"
33 #define KEY_ENVIRONMENTS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS"
34 #define KEY_CONTROL_PRINT "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT"
35 #define KEY_WINNT_PRINTERS "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
36 #define KEY_WINNT_PRINT "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT"
37 #define KEY_PORTS "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PORTS"
39 /* callback table for various registry paths below the ones we service in this module */
41 struct reg_dyn_tree {
42 /* full key path in normalized form */
43 const char *path;
45 /* callbscks for fetch/store operations */
46 int ( *fetch_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
47 BOOL (*store_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
48 int (*fetch_values) ( const char *path, REGVAL_CTR *values );
49 BOOL (*store_values) ( const char *path, REGVAL_CTR *values );
53 /**********************************************************************
54 move to next non-delimter character
55 *********************************************************************/
57 static char* remaining_path( const char *key )
59 static pstring new_path;
60 char *p;
62 if ( !key || !*key )
63 return NULL;
65 pstrcpy( new_path, key );
66 /* normalize_reg_path( new_path ); */
68 if ( !(p = strchr( new_path, '\\' )) )
70 if ( !(p = strchr( new_path, '/' )) )
71 p = new_path;
72 else
73 p++;
75 else
76 p++;
78 return p;
81 /***********************************************************************
82 simple function to prune a pathname down to the basename of a file
83 **********************************************************************/
85 static char* dos_basename ( char *path )
87 char *p;
89 if ( !(p = strrchr( path, '\\' )) )
90 p = path;
91 else
92 p++;
94 return p;
97 /**********************************************************************
98 *********************************************************************/
100 static int key_forms_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
102 char *p = remaining_path( key + strlen(KEY_FORMS) );
104 /* no keys below Forms */
106 if ( p )
107 return -1;
109 return 0;
112 static int key_forms_fetch_values( const char *key, REGVAL_CTR *values )
114 uint32 data[8];
115 int i, num_values, form_index = 1;
116 nt_forms_struct *forms_list = NULL;
117 nt_forms_struct *form;
119 DEBUG(10,("print_values_forms: key=>[%s]\n", key ? key : "NULL" ));
121 num_values = get_ntforms( &forms_list );
123 DEBUG(10,("hive_forms_fetch_values: [%d] user defined forms returned\n",
124 num_values));
126 /* handle user defined forms */
128 for ( i=0; i<num_values; i++ ) {
129 form = &forms_list[i];
131 data[0] = form->width;
132 data[1] = form->length;
133 data[2] = form->left;
134 data[3] = form->top;
135 data[4] = form->right;
136 data[5] = form->bottom;
137 data[6] = form_index++;
138 data[7] = form->flag;
140 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );
143 SAFE_FREE( forms_list );
144 forms_list = NULL;
146 /* handle built-on forms */
148 num_values = get_builtin_ntforms( &forms_list );
150 DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n",
151 num_values));
153 for ( i=0; i<num_values; i++ ) {
154 form = &forms_list[i];
156 data[0] = form->width;
157 data[1] = form->length;
158 data[2] = form->left;
159 data[3] = form->top;
160 data[4] = form->right;
161 data[5] = form->bottom;
162 data[6] = form_index++;
163 data[7] = form->flag;
165 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );
168 SAFE_FREE( forms_list );
170 return regval_ctr_numvals( values );
173 /**********************************************************************
174 *********************************************************************/
176 static int key_printer_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
178 int n_services = lp_numservices();
179 int snum;
180 fstring sname;
181 int i;
182 int num_subkeys = 0;
183 char *keystr;
184 char *base, *new_path;
185 NT_PRINTER_INFO_LEVEL *printer = NULL;
186 fstring *subkey_names = NULL;
187 pstring path;
189 DEBUG(10,("print_subpath_printers: key=>[%s]\n", key ? key : "NULL" ));
191 pstrcpy( path, key );
192 normalize_reg_path( path );
194 /* normalizing the path does not change length, just key delimiters and case */
196 if ( strncmp( path, KEY_WINNT_PRINTERS, strlen(KEY_WINNT_PRINTERS) ) == 0 )
197 keystr = remaining_path( key + strlen(KEY_WINNT_PRINTERS) );
198 else
199 keystr = remaining_path( key + strlen(KEY_CONTROL_PRINTERS) );
202 if ( !keystr ) {
203 /* enumerate all printers */
205 for (snum=0; snum<n_services; snum++) {
206 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
207 continue;
209 /* don't report the [printers] share */
211 if ( strequal( lp_servicename(snum), PRINTERS_NAME ) )
212 continue;
214 fstrcpy( sname, lp_servicename(snum) );
216 regsubkey_ctr_addkey( subkeys, sname );
219 num_subkeys = regsubkey_ctr_numkeys( subkeys );
220 goto done;
223 /* get information for a specific printer */
225 reg_split_path( keystr, &base, &new_path );
227 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, base) ) )
228 goto done;
230 num_subkeys = get_printer_subkeys( &printer->info_2->data, new_path?new_path:"", &subkey_names );
232 for ( i=0; i<num_subkeys; i++ )
233 regsubkey_ctr_addkey( subkeys, subkey_names[i] );
235 free_a_printer( &printer, 2 );
237 /* no other subkeys below here */
239 done:
240 SAFE_FREE( subkey_names );
242 return num_subkeys;
245 static BOOL key_printer_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
247 return True;
250 static int key_printer_fetch_values( const char *key, REGVAL_CTR *values )
252 int num_values = 0;
253 char *keystr, *key2 = NULL;
254 char *base, *new_path;
255 NT_PRINTER_INFO_LEVEL *printer = NULL;
256 NT_PRINTER_INFO_LEVEL_2 *info2;
257 DEVICEMODE *devmode;
258 prs_struct prs;
259 uint32 offset;
260 int snum;
261 fstring printername;
262 NT_PRINTER_DATA *p_data;
263 int i, key_index;
264 UNISTR2 data;
265 pstring path;
268 * Theres are tw cases to deal with here
269 * (1) enumeration of printer_info_2 values
270 * (2) enumeration of the PrinterDriverData subney
273 pstrcpy( path, key );
274 normalize_reg_path( path );
276 /* normalizing the path does not change length, just key delimiters and case */
278 if ( strncmp( path, KEY_WINNT_PRINTERS, strlen(KEY_WINNT_PRINTERS) ) == 0 )
279 keystr = remaining_path( key + strlen(KEY_WINNT_PRINTERS) );
280 else
281 keystr = remaining_path( key + strlen(KEY_CONTROL_PRINTERS) );
283 if ( !keystr ) {
284 /* top level key has no values */
285 goto done;
288 key2 = SMB_STRDUP( keystr );
289 keystr = key2;
290 reg_split_path( keystr, &base, &new_path );
292 fstrcpy( printername, base );
294 if ( !new_path ) {
295 char *p;
296 uint32 printer_status = PRINTER_STATUS_OK;
298 /* we are dealing with the printer itself */
300 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
301 goto done;
303 info2 = printer->info_2;
306 regval_ctr_addvalue( values, "Attributes", REG_DWORD, (char*)&info2->attributes, sizeof(info2->attributes) );
307 regval_ctr_addvalue( values, "Priority", REG_DWORD, (char*)&info2->priority, sizeof(info2->attributes) );
308 regval_ctr_addvalue( values, "ChangeID", REG_DWORD, (char*)&info2->changeid, sizeof(info2->changeid) );
309 regval_ctr_addvalue( values, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) );
311 /* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */
312 regval_ctr_addvalue( values, "Status", REG_DWORD, (char*)&printer_status, sizeof(info2->status) );
314 regval_ctr_addvalue( values, "StartTime", REG_DWORD, (char*)&info2->starttime, sizeof(info2->starttime) );
315 regval_ctr_addvalue( values, "UntilTime", REG_DWORD, (char*)&info2->untiltime, sizeof(info2->untiltime) );
317 /* strip the \\server\ from this string */
318 if ( !(p = strrchr( info2->printername, '\\' ) ) )
319 p = info2->printername;
320 else
321 p++;
322 init_unistr2( &data, p, UNI_STR_TERMINATE);
323 regval_ctr_addvalue( values, "Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
325 init_unistr2( &data, info2->location, UNI_STR_TERMINATE);
326 regval_ctr_addvalue( values, "Location", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
328 init_unistr2( &data, info2->comment, UNI_STR_TERMINATE);
329 regval_ctr_addvalue( values, "Description", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
331 init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE);
332 regval_ctr_addvalue( values, "Parameters", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
334 init_unistr2( &data, info2->portname, UNI_STR_TERMINATE);
335 regval_ctr_addvalue( values, "Port", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
337 init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE);
338 regval_ctr_addvalue( values, "Share Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
340 init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE);
341 regval_ctr_addvalue( values, "Printer Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
343 init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE);
344 regval_ctr_addvalue( values, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
346 init_unistr2( &data, "WinPrint", UNI_STR_TERMINATE);
347 regval_ctr_addvalue( values, "Print Processor", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
349 init_unistr2( &data, "RAW", UNI_STR_TERMINATE);
350 regval_ctr_addvalue( values, "Datatype", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
353 /* use a prs_struct for converting the devmode and security
354 descriptor to REG_BINARY */
356 prs_init( &prs, MAX_PDU_FRAG_LEN, regval_ctr_getctx(values), MARSHALL);
358 /* stream the device mode */
360 snum = lp_servicenumber(info2->sharename);
361 if ( (devmode = construct_dev_mode( snum )) != NULL )
363 if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
365 offset = prs_offset( &prs );
367 regval_ctr_addvalue( values, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
373 prs_mem_clear( &prs );
374 prs_set_offset( &prs, 0 );
376 if ( info2->secdesc_buf && info2->secdesc_buf->len )
378 if ( sec_io_desc("sec_desc", &info2->secdesc_buf->sec, &prs, 0 ) ) {
380 offset = prs_offset( &prs );
382 regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&prs), offset );
386 prs_mem_free( &prs );
388 num_values = regval_ctr_numvals( values );
390 goto done;
394 /* now enumerate the key */
396 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
397 goto done;
399 /* iterate over all printer data and fill the regval container */
401 p_data = &printer->info_2->data;
402 if ( (key_index = lookup_printerkey( p_data, new_path )) == -1 ) {
403 DEBUG(10,("key_printer_fetch_values: Unknown keyname [%s]\n", new_path));
404 goto done;
407 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
409 for ( i=0; i<num_values; i++ )
410 regval_ctr_copyvalue( values, regval_ctr_specific_value(&p_data->keys[key_index].values, i) );
413 done:
414 if ( printer )
415 free_a_printer( &printer, 2 );
417 SAFE_FREE( key2 );
419 return num_values;
422 static BOOL key_printer_store_values( const char *key, REGVAL_CTR *values )
424 return True;
427 /**********************************************************************
428 *********************************************************************/
429 #define ENVIRONMENT_DRIVERS 1
430 #define ENVIRONMENT_PRINTPROC 2
432 static int key_driver_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
434 const char *environments[] = {
435 "Windows 4.0",
436 "Windows NT x86",
437 "Windows NT R4000",
438 "Windows NT Alpha_AXP",
439 "Windows NT PowerPC",
440 "Windows IA64",
441 "Windows x64",
442 NULL };
443 fstring *drivers = NULL;
444 int i, env_index, num_drivers;
445 char *keystr, *base, *subkeypath;
446 pstring key2;
447 int num_subkeys = -1;
448 int env_subkey_type = 0;
449 int version;
451 DEBUG(10,("key_driver_fetch_keys key=>[%s]\n", key ? key : "NULL" ));
453 keystr = remaining_path( key + strlen(KEY_ENVIRONMENTS) );
455 /* list all possible architectures */
457 if ( !keystr ) {
458 for ( num_subkeys=0; environments[num_subkeys]; num_subkeys++ )
459 regsubkey_ctr_addkey( subkeys, environments[num_subkeys] );
461 return num_subkeys;
464 /* we are dealing with a subkey of "Environments */
466 pstrcpy( key2, keystr );
467 keystr = key2;
468 reg_split_path( keystr, &base, &subkeypath );
470 /* sanity check */
472 for ( env_index=0; environments[env_index]; env_index++ ) {
473 if ( strequal( environments[env_index], base ) )
474 break;
476 if ( !environments[env_index] )
477 return -1;
479 /* ...\Print\Environements\...\ */
481 if ( !subkeypath ) {
482 regsubkey_ctr_addkey( subkeys, "Drivers" );
483 regsubkey_ctr_addkey( subkeys, "Print Processors" );
485 return 2;
488 /* more of the key path to process */
490 keystr = subkeypath;
491 reg_split_path( keystr, &base, &subkeypath );
493 /* ...\Print\Environements\...\Drivers\ */
495 if ( strequal(base, "Drivers") )
496 env_subkey_type = ENVIRONMENT_DRIVERS;
497 else if ( strequal(base, "Print Processors") )
498 env_subkey_type = ENVIRONMENT_PRINTPROC;
499 else
500 /* invalid path */
501 return -1;
503 if ( !subkeypath ) {
504 switch ( env_subkey_type ) {
505 case ENVIRONMENT_DRIVERS:
506 switch ( env_index ) {
507 case 0: /* Win9x */
508 regsubkey_ctr_addkey( subkeys, "Version-0" );
509 break;
510 default: /* Windows NT based systems */
511 regsubkey_ctr_addkey( subkeys, "Version-2" );
512 regsubkey_ctr_addkey( subkeys, "Version-3" );
513 break;
516 return regsubkey_ctr_numkeys( subkeys );
518 case ENVIRONMENT_PRINTPROC:
519 if ( env_index == 1 || env_index == 5 || env_index == 6 )
520 regsubkey_ctr_addkey( subkeys, "winprint" );
522 return regsubkey_ctr_numkeys( subkeys );
526 /* we finally get to enumerate the drivers */
528 keystr = subkeypath;
529 reg_split_path( keystr, &base, &subkeypath );
531 /* get thr print processors key out of the way */
532 if ( env_subkey_type == ENVIRONMENT_PRINTPROC ) {
533 if ( !strequal( base, "winprint" ) )
534 return -1;
535 return !subkeypath ? 0 : -1;
538 /* only dealing with drivers from here on out */
540 version = atoi(&base[strlen(base)-1]);
542 switch (env_index) {
543 case 0:
544 if ( version != 0 )
545 return -1;
546 break;
547 default:
548 if ( version != 2 && version != 3 )
549 return -1;
550 break;
554 if ( !subkeypath ) {
555 num_drivers = get_ntdrivers( &drivers, environments[env_index], version );
556 for ( i=0; i<num_drivers; i++ )
557 regsubkey_ctr_addkey( subkeys, drivers[i] );
559 return regsubkey_ctr_numkeys( subkeys );
562 /* if anything else left, just say if has no subkeys */
564 DEBUG(1,("key_driver_fetch_keys unhandled key [%s] (subkey == %s\n",
565 key, subkeypath ));
567 return 0;
570 static BOOL key_driver_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
572 return True;
575 static int key_driver_fetch_values( const char *key, REGVAL_CTR *values )
577 char *keystr, *base, *subkeypath;
578 pstring key2;
579 fstring arch_environment;
580 fstring driver;
581 int version;
582 NT_PRINTER_DRIVER_INFO_LEVEL driver_ctr;
583 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
584 WERROR w_result;
585 char *buffer = NULL;
586 char *buffer2 = NULL;
587 int buffer_size = 0;
588 int i, length;
589 char *filename;
590 UNISTR2 data;
591 int env_subkey_type = 0;
594 DEBUG(8,("key_driver_fetch_values: Enter key => [%s]\n", key ? key : "NULL"));
596 keystr = remaining_path( key + strlen(KEY_ENVIRONMENTS) );
598 if ( !keystr )
599 return 0;
601 /* The only keys below KEY_PRINTING\Environments is the
602 specific printer driver info */
604 /* environment */
606 pstrcpy( key2, keystr);
607 keystr = key2;
608 reg_split_path( keystr, &base, &subkeypath );
609 if ( !subkeypath )
610 return 0;
611 fstrcpy( arch_environment, base );
613 /* Driver */
615 keystr = subkeypath;
616 reg_split_path( keystr, &base, &subkeypath );
618 if ( strequal(base, "Drivers") )
619 env_subkey_type = ENVIRONMENT_DRIVERS;
620 else if ( strequal(base, "Print Processors") )
621 env_subkey_type = ENVIRONMENT_PRINTPROC;
622 else
623 /* invalid path */
624 return -1;
626 if ( !subkeypath )
627 return 0;
629 /* for now bail out if we are seeing anything other than the drivers key */
631 if ( env_subkey_type == ENVIRONMENT_PRINTPROC )
632 return 0;
634 keystr = subkeypath;
635 reg_split_path( keystr, &base, &subkeypath );
637 /* no values under Version-XX */
639 if ( !subkeypath )
640 return 0;
642 version = atoi(&base[strlen(base)-1]);
644 /* printer driver name */
646 keystr = subkeypath;
647 reg_split_path( keystr, &base, &subkeypath );
648 /* don't go any deeper for now */
649 if ( subkeypath )
650 return 0;
651 fstrcpy( driver, base );
653 w_result = get_a_printer_driver( &driver_ctr, 3, driver, arch_environment, version );
655 if ( !W_ERROR_IS_OK(w_result) )
656 return -1;
658 /* build the values out of the driver information */
659 info3 = driver_ctr.info_3;
661 filename = dos_basename( info3->driverpath );
662 init_unistr2( &data, filename, UNI_STR_TERMINATE);
663 regval_ctr_addvalue( values, "Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
665 filename = dos_basename( info3->configfile );
666 init_unistr2( &data, filename, UNI_STR_TERMINATE);
667 regval_ctr_addvalue( values, "Configuration File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
669 filename = dos_basename( info3->datafile );
670 init_unistr2( &data, filename, UNI_STR_TERMINATE);
671 regval_ctr_addvalue( values, "Data File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
673 filename = dos_basename( info3->helpfile );
674 init_unistr2( &data, filename, UNI_STR_TERMINATE);
675 regval_ctr_addvalue( values, "Help File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
677 init_unistr2( &data, info3->defaultdatatype, UNI_STR_TERMINATE);
678 regval_ctr_addvalue( values, "Data Type", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
680 regval_ctr_addvalue( values, "Version", REG_DWORD, (char*)&info3->cversion, sizeof(info3->cversion) );
682 if ( info3->dependentfiles ) {
683 /* place the list of dependent files in a single
684 character buffer, separating each file name by
685 a NULL */
687 for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ ) {
688 /* strip the path to only the file's base name */
690 filename = dos_basename( info3->dependentfiles[i] );
692 length = strlen(filename);
694 buffer2 = SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
695 if ( !buffer2 )
696 break;
697 buffer = buffer2;
699 init_unistr2( &data, filename, UNI_STR_TERMINATE);
700 memcpy( buffer+buffer_size, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
702 buffer_size += (length + 1)*sizeof(uint16);
705 /* terminated by double NULL. Add the final one here */
707 buffer2 = SMB_REALLOC( buffer, buffer_size + 2 );
708 if ( !buffer2 ) {
709 SAFE_FREE( buffer );
710 buffer_size = 0;
711 } else {
712 buffer = buffer2;
713 buffer[buffer_size++] = '\0';
714 buffer[buffer_size++] = '\0';
718 regval_ctr_addvalue( values, "Dependent Files", REG_MULTI_SZ, buffer, buffer_size );
720 free_a_printer_driver( driver_ctr, 3 );
722 SAFE_FREE( buffer );
724 DEBUG(8,("key_driver_fetch_values: Exit\n"));
726 return regval_ctr_numvals( values );
729 static BOOL key_driver_store_values( const char *key, REGVAL_CTR *values )
731 return True;
734 /**********************************************************************
735 Deal with the 'Print' key the same whether it came from SYSTEM
736 or SOFTWARE
737 *********************************************************************/
739 static int key_print_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
741 int key_len = strlen(key);
743 /* no keys below 'Print' handled here */
745 if ( (key_len != strlen(KEY_CONTROL_PRINT)) && (key_len != strlen(KEY_WINNT_PRINT)) )
746 return -1;
748 regsubkey_ctr_addkey( subkeys, "Environments" );
749 regsubkey_ctr_addkey( subkeys, "Monitors" );
750 regsubkey_ctr_addkey( subkeys, "Forms" );
751 regsubkey_ctr_addkey( subkeys, "Printers" );
753 return regsubkey_ctr_numkeys( subkeys );
756 /**********************************************************************
757 If I can get rid of the 'enumports command', this code becomes
758 a tdb lookup.
759 *********************************************************************/
761 static int key_ports_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
763 /* no keys below ports */
765 if ( remaining_path( key + strlen(KEY_PORTS) ) )
766 return -1;
768 return 0;
771 static BOOL key_ports_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
773 return True;
776 static int key_ports_fetch_values( const char *key, REGVAL_CTR *values )
778 int numlines, i;
779 char **lines;
780 UNISTR2 data;
781 WERROR result;
782 char *p = remaining_path( key + strlen(KEY_PORTS) );
784 /* no keys below ports */
785 if ( p )
786 return -1;
788 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &lines )) )
789 return -1;
791 init_unistr2( &data, "", UNI_STR_TERMINATE);
792 for ( i=0; i<numlines; i++ )
793 regval_ctr_addvalue( values, lines[i], REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
795 return regval_ctr_numvals( values );
798 static BOOL key_ports_store_values( const char *key, REGVAL_CTR *values )
800 return True;
803 /**********************************************************************
804 Structure to hold dispatch table of ops for various printer keys.
805 Make sure to always store deeper keys along the same path first so
806 we ge a more specific match.
807 *********************************************************************/
809 static struct reg_dyn_tree print_registry[] = {
810 /* just pass the monitor onto the registry tdb */
811 { KEY_MONITORS,
812 &regdb_fetch_keys,
813 &regdb_store_keys,
814 &regdb_fetch_values,
815 &regdb_store_values },
816 { KEY_FORMS,
817 &key_forms_fetch_keys,
818 NULL,
819 &key_forms_fetch_values,
820 NULL },
821 { KEY_CONTROL_PRINTERS,
822 &key_printer_fetch_keys,
823 &key_printer_store_keys,
824 &key_printer_fetch_values,
825 &key_printer_store_values },
826 { KEY_ENVIRONMENTS,
827 &key_driver_fetch_keys,
828 &key_driver_store_keys,
829 &key_driver_fetch_values,
830 &key_driver_store_values },
831 { KEY_CONTROL_PRINT,
832 &key_print_fetch_keys,
833 NULL,
834 NULL,
835 NULL },
836 { KEY_WINNT_PRINTERS,
837 &key_printer_fetch_keys,
838 &key_printer_store_keys,
839 &key_printer_fetch_values,
840 &key_printer_store_values },
841 { KEY_PORTS,
842 &key_ports_fetch_keys,
843 &key_ports_store_keys,
844 &key_ports_fetch_values,
845 &key_ports_store_values },
847 { NULL, NULL, NULL, NULL, NULL }
851 /**********************************************************************
852 *********************************************************************/
854 static int match_registry_path( const char *key )
856 int i;
857 pstring path;
859 if ( !key )
860 return -1;
862 pstrcpy( path, key );
863 normalize_reg_path( path );
865 for ( i=0; print_registry[i].path; i++ ) {
866 if ( strncmp( path, print_registry[i].path, strlen(print_registry[i].path) ) == 0 )
867 return i;
870 return -1;
873 /**********************************************************************
874 *********************************************************************/
876 static int regprint_fetch_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
878 int i = match_registry_path( key );
880 if ( i == -1 )
881 return -1;
883 if ( !print_registry[i].fetch_subkeys )
884 return -1;
886 return print_registry[i].fetch_subkeys( key, subkeys );
889 /**********************************************************************
890 *********************************************************************/
892 static BOOL regprint_store_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
894 int i = match_registry_path( key );
896 if ( i == -1 )
897 return False;
899 if ( !print_registry[i].store_subkeys )
900 return False;
902 return print_registry[i].store_subkeys( key, subkeys );
905 /**********************************************************************
906 *********************************************************************/
908 static int regprint_fetch_reg_values( const char *key, REGVAL_CTR *values )
910 int i = match_registry_path( key );
912 if ( i == -1 )
913 return -1;
915 /* return 0 values by default since we know the key had
916 to exist because the client opened a handle */
918 if ( !print_registry[i].fetch_values )
919 return 0;
921 return print_registry[i].fetch_values( key, values );
924 /**********************************************************************
925 *********************************************************************/
927 static BOOL regprint_store_reg_values( const char *key, REGVAL_CTR *values )
929 int i = match_registry_path( key );
931 if ( i == -1 )
932 return False;
934 if ( !print_registry[i].store_values )
935 return False;
937 return print_registry[i].store_values( key, values );
941 * Table of function pointers for accessing printing data
944 REGISTRY_OPS printing_ops = {
945 regprint_fetch_reg_keys,
946 regprint_fetch_reg_values,
947 regprint_store_reg_keys,
948 regprint_store_reg_values,
949 NULL