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 */
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_DRIVERS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS/.../DRIVERS"
34 #define KEY_PRINTPROC "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS/.../PRINTPROC"
35 #define KEY_ENVIRONMENTS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS"
36 #define KEY_CONTROL_PRINT "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT"
37 #define KEY_WINNT_PRINTERS "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
38 #define KEY_WINNT_PRINT "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT"
39 #define KEY_PORTS "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PORTS"
41 /* callback table for various registry paths below the ones we service in this module */
44 /* full key path in normalized form */
47 /* callbscks for fetch/store operations */
48 int ( *fetch_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
49 BOOL (*store_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
50 int (*fetch_values) ( const char *path, REGVAL_CTR *values );
51 BOOL (*store_values) ( const char *path, REGVAL_CTR *values );
56 /**********************************************************************
57 handle enumeration of subkeys below KEY_PRINTING\Printers
58 *********************************************************************/
60 static int print_subpath_printers( char *key, REGSUBKEY_CTR *subkeys )
62 int n_services = lp_numservices();
67 char *keystr, *key2 = NULL;
68 char *base, *new_path;
69 NT_PRINTER_INFO_LEVEL *printer = NULL;
70 fstring *subkey_names = NULL;
72 DEBUG(10,("print_subpath_printers: key=>[%s]\n", key ? key : "NULL" ));
76 /* enumerate all printers */
78 for (snum=0; snum<n_services; snum++) {
79 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
82 /* don't report the [printers] share */
84 if ( strequal( lp_servicename(snum), PRINTERS_NAME ) )
87 fstrcpy( sname, lp_servicename(snum) );
89 regsubkey_ctr_addkey( subkeys, sname );
92 num_subkeys = regsubkey_ctr_numkeys( subkeys );
96 /* get information for a specific printer */
98 key2 = SMB_STRDUP( key );
100 reg_split_path( keystr, &base, &new_path );
102 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, base) ) )
105 num_subkeys = get_printer_subkeys( &printer->info_2->data, new_path?new_path:"", &subkey_names );
107 for ( i=0; i<num_subkeys; i++ )
108 regsubkey_ctr_addkey( subkeys, subkey_names[i] );
110 free_a_printer( &printer, 2 );
112 /* no other subkeys below here */
116 SAFE_FREE( subkey_names );
121 /**********************************************************************
122 handle enumeration of values below KEY_PRINTING\Printers
123 *********************************************************************/
125 static int print_subpath_values_printers( char *key, REGVAL_CTR *val )
128 char *keystr, *key2 = NULL;
129 char *base, *new_path;
130 NT_PRINTER_INFO_LEVEL *printer = NULL;
131 NT_PRINTER_INFO_LEVEL_2 *info2;
137 NT_PRINTER_DATA *p_data;
142 * Theres are tw cases to deal with here
143 * (1) enumeration of printer_info_2 values
144 * (2) enumeration of the PrinterDriverData subney
148 /* top level key has no values */
152 key2 = SMB_STRDUP( key );
154 reg_split_path( keystr, &base, &new_path );
156 fstrcpy( printername, base );
160 uint32 printer_status = PRINTER_STATUS_OK;
162 /* we are dealing with the printer itself */
164 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
167 info2 = printer->info_2;
170 regval_ctr_addvalue( val, "Attributes", REG_DWORD, (char*)&info2->attributes, sizeof(info2->attributes) );
171 regval_ctr_addvalue( val, "Priority", REG_DWORD, (char*)&info2->priority, sizeof(info2->attributes) );
172 regval_ctr_addvalue( val, "ChangeID", REG_DWORD, (char*)&info2->changeid, sizeof(info2->changeid) );
173 regval_ctr_addvalue( val, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) );
175 /* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */
176 regval_ctr_addvalue( val, "Status", REG_DWORD, (char*)&printer_status, sizeof(info2->status) );
178 regval_ctr_addvalue( val, "StartTime", REG_DWORD, (char*)&info2->starttime, sizeof(info2->starttime) );
179 regval_ctr_addvalue( val, "UntilTime", REG_DWORD, (char*)&info2->untiltime, sizeof(info2->untiltime) );
181 /* strip the \\server\ from this string */
182 if ( !(p = strrchr( info2->printername, '\\' ) ) )
183 p = info2->printername;
186 init_unistr2( &data, p, UNI_STR_TERMINATE);
187 regval_ctr_addvalue( val, "Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
189 init_unistr2( &data, info2->location, UNI_STR_TERMINATE);
190 regval_ctr_addvalue( val, "Location", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
192 init_unistr2( &data, info2->comment, UNI_STR_TERMINATE);
193 regval_ctr_addvalue( val, "Description", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
195 init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE);
196 regval_ctr_addvalue( val, "Parameters", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
198 init_unistr2( &data, info2->portname, UNI_STR_TERMINATE);
199 regval_ctr_addvalue( val, "Port", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
201 init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE);
202 regval_ctr_addvalue( val, "Share Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
204 init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE);
205 regval_ctr_addvalue( val, "Printer Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
207 init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE);
208 regval_ctr_addvalue( val, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
210 init_unistr2( &data, "WinPrint", UNI_STR_TERMINATE);
211 regval_ctr_addvalue( val, "Print Processor", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
213 init_unistr2( &data, "RAW", UNI_STR_TERMINATE);
214 regval_ctr_addvalue( val, "Datatype", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
217 /* use a prs_struct for converting the devmode and security
218 descriptor to REG_BINARY */
220 prs_init( &prs, MAX_PDU_FRAG_LEN, regval_ctr_getctx(val), MARSHALL);
222 /* stream the device mode */
224 snum = lp_servicenumber(info2->sharename);
225 if ( (devmode = construct_dev_mode( snum )) != NULL )
227 if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
229 offset = prs_offset( &prs );
231 regval_ctr_addvalue( val, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
237 prs_mem_clear( &prs );
238 prs_set_offset( &prs, 0 );
240 if ( info2->secdesc_buf && info2->secdesc_buf->len )
242 if ( sec_io_desc("sec_desc", &info2->secdesc_buf->sec, &prs, 0 ) ) {
244 offset = prs_offset( &prs );
246 regval_ctr_addvalue( val, "Security", REG_BINARY, prs_data_p(&prs), offset );
250 prs_mem_free( &prs );
252 num_values = regval_ctr_numvals( val );
258 /* now enumerate the key */
260 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
263 /* iterate over all printer data and fill the regval container */
265 p_data = &printer->info_2->data;
266 if ( (key_index = lookup_printerkey( p_data, new_path )) == -1 ) {
267 DEBUG(10,("print_subpath_values_printer: Unknown keyname [%s]\n", new_path));
271 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
273 for ( i=0; i<num_values; i++ )
274 regval_ctr_copyvalue( val, regval_ctr_specific_value(&p_data->keys[key_index].values, i) );
279 free_a_printer( &printer, 2 );
286 /**********************************************************************
287 Routine to handle enumeration of subkeys and values
288 below KEY_PRINTING (depending on whether or not subkeys/val are
290 *********************************************************************/
292 static int handle_printing_subpath( char *key, REGSUBKEY_CTR *subkeys, REGVAL_CTR *val )
298 DEBUG(10,("handle_printing_subpath: key=>[%s]\n", key ));
301 * break off the first part of the path
302 * topmost base **must** be one of the strings
303 * in top_level_keys[]
306 reg_split_path( key, &base, &p);
308 for ( i=0; i<MAX_TOP_LEVEL_KEYS; i++ ) {
309 if ( StrCaseCmp( top_level_keys[i], base ) == 0 )
313 DEBUG(10,("handle_printing_subpath: base=>[%s], i==[%d]\n", base, i));
315 if ( !(i < MAX_TOP_LEVEL_KEYS) )
318 /* Call routine to handle each top level key */
321 case KEY_INDEX_ENVIR:
323 print_subpath_environments( p, subkeys );
325 print_subpath_values_environments( p, val );
328 case KEY_INDEX_FORMS:
330 print_subpath_forms( p, subkeys );
332 print_subpath_values_forms( p, val );
335 case KEY_INDEX_PRINTER:
337 print_subpath_printers( p, subkeys );
339 print_subpath_values_printers( p, val );
342 /* default case for top level key that has no handler */
354 /**********************************************************************
355 Enumerate registry subkey names given a registry path.
356 Caller is responsible for freeing memory to **subkeys
357 *********************************************************************/
359 static int printing_subkey_info( const char *key, REGSUBKEY_CTR *subkey_ctr )
364 DEBUG(10,("printing_subkey_info: key=>[%s]\n", key));
366 path = trim_reg_path( key );
368 /* check to see if we are dealing with the top level key */
371 num_subkeys = handle_printing_subpath( path, subkey_ctr, NULL );
376 /* handle top level keys here */
378 if ( strequal( KEY_PRINTING, key ) ) {
379 regsubkey_ctr_addkey( subkey_ctr, "Environments" );
380 regsubkey_ctr_addkey( subkey_ctr, "Forms" );
382 else if ( strequal( KEY_PRINTING_2K, key ) ) {
383 regsubkey_ctr_addkey( subkey_ctr, "Printers" );
391 /**********************************************************************
392 move to next non-delimter character
393 *********************************************************************/
395 static char* remaining_path( const char *key )
397 static pstring new_path;
403 pstrcpy( new_path, key );
404 normalize_reg_path( new_path );
406 p = strchr( new_path, '/' );
416 /***********************************************************************
417 simple function to prune a pathname down to the basename of a file
418 **********************************************************************/
420 static char* dos_basename ( char *path )
424 p = strrchr( path, '\\' );
433 /**********************************************************************
434 *********************************************************************/
436 static int key_forms_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
441 static BOOL key_forms_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
446 static int key_forms_fetch_values( const char *key, REGVAL_CTR *values )
453 DEBUG(10,("print_values_forms: key=>[%s]\n", key ? key : "NULL" ));
455 nt_forms_struct *forms_list = NULL;
456 nt_forms_struct *form = NULL;
458 if ( (num_values = get_ntforms( &forms_list )) == 0 )
461 DEBUG(10,("hive_forms_fetch_values: [%d] user defined forms returned\n",
464 /* handle user defined forms */
466 for ( i=0; i<num_values; i++ ) {
467 form = &forms_list[i];
469 data[0] = form->width;
470 data[1] = form->length;
471 data[2] = form->left;
473 data[4] = form->right;
474 data[5] = form->bottom;
475 data[6] = form_index++;
476 data[7] = form->flag;
478 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );
481 SAFE_FREE( forms_list );
484 /* handle built-on forms */
486 if ( (num_values = get_builtin_ntforms( &forms_list )) == 0 )
489 DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n",
492 for ( i=0; i<num_values; i++ ) {
493 form = &forms_list[i];
495 data[0] = form->width;
496 data[1] = form->length;
497 data[2] = form->left;
499 data[4] = form->right;
500 data[5] = form->bottom;
501 data[6] = form_index++;
502 data[7] = form->flag;
504 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );
507 SAFE_FREE( forms_list );
509 return regval_ctr_numvals( values );
512 static BOOL key_forms_store_values( const char *key, REGVAL_CTR *values )
517 /**********************************************************************
518 *********************************************************************/
520 static int key_printer_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
525 static BOOL key_printer_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
530 static int key_printer_fetch_values( const char *key, REGVAL_CTR *values )
535 static BOOL key_printer_store_values( const char *key, REGVAL_CTR *values )
540 /**********************************************************************
541 *********************************************************************/
542 #define ENVIRONMENT_DRIVERS 1
543 #define ENVIRONMENT_PRINTPROC 2
545 static int key_driver_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
547 const char *environments[] = {
551 "Windows NT Alpha_AXP",
552 "Windows NT PowerPC",
556 fstring *drivers = NULL;
557 int i, env_index, num_drivers;
558 char *keystr, *base, *subkeypath;
560 int num_subkeys = -1;
561 int env_subkey_type = 0;
564 DEBUG(10,("print_subpath_environments: key=>[%s]\n", key ? key : "NULL" ));
566 /* list all possible architectures */
569 for ( num_subkeys=0; environments[num_subkeys]; num_subkeys++ )
570 regsubkey_ctr_addkey( subkeys, environments[num_subkeys] );
575 /* we are dealing with a subkey of "Environments */
577 pstrcpy( key2, key );
579 reg_split_path( keystr, &base, &subkeypath );
583 for ( env_index=0; environments[env_index]; env_index++ ) {
584 if ( strequal( environments[env_index], base ) )
587 if ( !environments[env_index] )
590 /* ...\Print\Environements\...\ */
593 regsubkey_ctr_addkey( subkeys, "Drivers" );
594 regsubkey_ctr_addkey( subkeys, "Print Processors" );
599 /* more of the key path to process */
602 reg_split_path( keystr, &base, &subkeypath );
604 /* ...\Print\Environements\...\Drivers\ */
606 if ( strequal(base, "Drivers") )
607 env_subkey_type = ENVIRONMENT_DRIVERS;
608 else if ( strequal(base, "Print Processors") )
609 env_subkey_type = ENVIRONMENT_PRINTPROC;
615 switch ( env_subkey_type ) {
616 case ENVIRONMENT_DRIVERS:
617 switch ( env_index ) {
619 regsubkey_ctr_addkey( subkeys, "Version-0" );
621 default: /* Windows NT based systems */
622 regsubkey_ctr_addkey( subkeys, "Version-2" );
623 regsubkey_ctr_addkey( subkeys, "Version-3" );
627 return regsubkey_ctr_numkeys( subkeys );
629 case ENVIRONMENT_PRINTPROC:
630 if ( env_index == 1 || env_index == 5 || env_index == 6 )
631 regsubkey_ctr_addkey( subkeys, "winprint" );
633 return regsubkey_ctr_numkeys( subkeys );
637 /* we finally get to enumerate the drivers */
640 reg_split_path( keystr, &base, &subkeypath );
642 /* get thr print processors key out of the way */
643 if ( env_subkey_type == ENVIRONMENT_PRINTPROC ) {
644 if ( !strequal( base, "winprint" ) )
646 return !subkeypath ? 0 : -1;
649 /* only dealing with drivers from here on out */
651 version = atoi(&base[strlen(base)-1]);
659 if ( version != 2 && version != 3 )
666 num_drivers = get_ntdrivers( &drivers, environments[env_index], version );
667 for ( i=0; i<num_drivers; i++ )
668 regsubkey_ctr_addkey( subkeys, drivers[i] );
670 return regsubkey_ctr_numkeys( subkeys );
673 /* if anything else left, just say if has no subkeys */
675 DEBUG(1,("print_subpath_environments: unhandled key [%s] (subkey == %s\n",
681 static BOOL key_driver_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
686 static int key_driver_fetch_values( const char *key, REGVAL_CTR *values )
688 char *keystr, *base, *subkeypath;
690 fstring arch_environment;
693 NT_PRINTER_DRIVER_INFO_LEVEL driver_ctr;
694 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
697 char *buffer2 = NULL;
702 int env_subkey_type = 0;
705 DEBUG(8,("print_subpath_values_environments: Enter key => [%s]\n", key ? key : "NULL"));
710 /* The only keys below KEY_PRINTING\Environments is the
711 specific printer driver info */
715 pstrcpy( key2, key );
717 reg_split_path( keystr, &base, &subkeypath );
720 fstrcpy( arch_environment, base );
725 reg_split_path( keystr, &base, &subkeypath );
727 if ( strequal(base, "Drivers") )
728 env_subkey_type = ENVIRONMENT_DRIVERS;
729 else if ( strequal(base, "Print Processors") )
730 env_subkey_type = ENVIRONMENT_PRINTPROC;
738 /* for now bail out if we are seeing anything other than the drivers key */
740 if ( env_subkey_type == ENVIRONMENT_PRINTPROC )
744 reg_split_path( keystr, &base, &subkeypath );
746 version = atoi(&base[strlen(base)-1]);
748 /* printer driver name */
751 reg_split_path( keystr, &base, &subkeypath );
752 /* don't go any deeper for now */
755 fstrcpy( driver, base );
757 w_result = get_a_printer_driver( &driver_ctr, 3, driver, arch_environment, version );
759 if ( !W_ERROR_IS_OK(w_result) )
762 /* build the values out of the driver information */
763 info3 = driver_ctr.info_3;
765 filename = dos_basename( info3->driverpath );
766 init_unistr2( &data, filename, UNI_STR_TERMINATE);
767 regval_ctr_addvalue( values, "Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
769 filename = dos_basename( info3->configfile );
770 init_unistr2( &data, filename, UNI_STR_TERMINATE);
771 regval_ctr_addvalue( values, "Configuration File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
773 filename = dos_basename( info3->datafile );
774 init_unistr2( &data, filename, UNI_STR_TERMINATE);
775 regval_ctr_addvalue( values, "Data File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
777 filename = dos_basename( info3->helpfile );
778 init_unistr2( &data, filename, UNI_STR_TERMINATE);
779 regval_ctr_addvalue( values, "Help File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
781 init_unistr2( &data, info3->defaultdatatype, UNI_STR_TERMINATE);
782 regval_ctr_addvalue( values, "Data Type", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
784 regval_ctr_addvalue( values, "Version", REG_DWORD, (char*)&info3->cversion, sizeof(info3->cversion) );
786 if ( info3->dependentfiles ) {
787 /* place the list of dependent files in a single
788 character buffer, separating each file name by
791 for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ ) {
792 /* strip the path to only the file's base name */
794 filename = dos_basename( info3->dependentfiles[i] );
796 length = strlen(filename);
798 buffer2 = SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
803 init_unistr2( &data, filename, UNI_STR_TERMINATE);
804 memcpy( buffer+buffer_size, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
806 buffer_size += (length + 1)*sizeof(uint16);
809 /* terminated by double NULL. Add the final one here */
811 buffer2 = SMB_REALLOC( buffer, buffer_size + 2 );
817 buffer[buffer_size++] = '\0';
818 buffer[buffer_size++] = '\0';
822 regval_ctr_addvalue( values, "Dependent Files", REG_MULTI_SZ, buffer, buffer_size );
824 free_a_printer_driver( driver_ctr, 3 );
828 DEBUG(8,("print_subpath_values_environments: Exit\n"));
830 return regval_ctr_numvals( values );
833 static BOOL key_driver_store_values( const char *key, REGVAL_CTR *values )
838 /**********************************************************************
839 Deal with the 'Print' key the same whether it came from SYSTEM
841 *********************************************************************/
843 static int key_print_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
845 int key_len = strlen(key);
847 /* no keys below 'Print' handled here */
849 if ( (key_len != strlen(KEY_CONTROL_PRINT)) && (key_len != strlen(KEY_WINNT_PRINT)) )
852 regsubkey_ctr_addkey( subkeys, "Environments" );
853 regsubkey_ctr_addkey( subkeys, "Monitors" );
854 regsubkey_ctr_addkey( subkeys, "Forms" );
855 regsubkey_ctr_addkey( subkeys, "Printers" );
857 return regsubkey_ctr_numkeys( subkeys );
860 /**********************************************************************
861 *********************************************************************/
863 static int key_ports_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
865 char *p = remaining_path( key + strlen(KEY_PORTS) );
867 /* no keys below ports */
874 static BOOL key_ports_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
879 static int key_ports_fetch_values( const char *key, REGVAL_CTR *values )
885 char *p = remaining_path( key + strlen(KEY_PORTS) );
887 /* no keys below ports */
891 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &lines )) )
894 init_unistr2( &data, "", UNI_STR_TERMINATE);
895 for ( i=0; i<numlines; i++ )
896 regval_ctr_addvalue( values, lines[i], REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
898 return regval_ctr_numvals( values );
901 static BOOL key_ports_store_values( const char *key, REGVAL_CTR *values )
906 /**********************************************************************
907 Structure to hold dispatch table of ops for various printer keys.
908 Make sure to always store deeper keys along the same path first so
909 we ge a more specific match.
910 *********************************************************************/
912 static struct reg_dyn_tree print_registry[] = {
913 /* just pass the monitor onto the regostry tdb */
918 ®db_store_values },
920 &key_forms_fetch_keys,
921 &key_forms_store_keys,
922 &key_forms_fetch_values,
923 &key_forms_store_values },
924 { KEY_CONTROL_PRINTERS,
925 &key_printer_fetch_keys,
926 &key_printer_store_keys,
927 &key_printer_fetch_values,
928 &key_printer_store_values },
930 &key_driver_fetch_keys,
931 &key_driver_store_keys,
932 &key_driver_fetch_values,
933 &key_driver_store_values },
935 &key_print_fetch_keys,
939 { KEY_WINNT_PRINTERS,
940 &key_printer_fetch_keys,
941 &key_printer_store_keys,
942 &key_printer_fetch_values,
943 &key_printer_store_values },
945 &key_print_fetch_keys,
950 &key_ports_fetch_keys,
951 &key_ports_store_keys,
952 &key_ports_fetch_values,
953 &key_ports_store_values },
955 { NULL, NULL, NULL, NULL, NULL }
959 /**********************************************************************
960 *********************************************************************/
962 static int match_registry_path( const char *key )
970 pstrcpy( path, key );
971 normalize_reg_path( path );
973 for ( i=0; print_registry[i].path; i++ ) {
974 if ( strncmp( path, print_registry[i].path, strlen(print_registry[i].path) ) == 0 )
981 /**********************************************************************
982 *********************************************************************/
984 static int regprint_fetch_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
986 int i = match_registry_path( key );
991 if ( !print_registry[i].fetch_subkeys )
994 return print_registry[i].fetch_subkeys( key, subkeys );
997 /**********************************************************************
998 *********************************************************************/
1000 static BOOL regprint_store_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
1002 int i = match_registry_path( key );
1007 if ( !print_registry[i].store_subkeys )
1010 return print_registry[i].store_subkeys( key, subkeys );
1013 /**********************************************************************
1014 *********************************************************************/
1016 static int regprint_fetch_reg_values( const char *key, REGVAL_CTR *values )
1018 int i = match_registry_path( key );
1023 /* return 0 values by default since we know the key had
1024 to exist because the client opened a handle */
1026 if ( !print_registry[i].fetch_values )
1029 return print_registry[i].fetch_values( key, values );
1032 /**********************************************************************
1033 *********************************************************************/
1035 static BOOL regprint_store_reg_values( const char *key, REGVAL_CTR *values )
1037 int i = match_registry_path( key );
1042 if ( !print_registry[i].store_values )
1045 return print_registry[i].store_values( key, values );
1049 * Table of function pointers for accessing printing data
1052 REGISTRY_OPS printing_ops = {
1053 regprint_fetch_reg_keys,
1054 regprint_fetch_reg_values,
1055 regprint_store_reg_keys,
1056 regprint_store_reg_values,