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_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 */
42 /* full key path in normalized form */
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
;
65 pstrcpy( new_path
, key
);
66 /* normalize_reg_path( new_path ); */
68 if ( !(p
= strchr( new_path
, '\\' )) )
70 if ( !(p
= strchr( new_path
, '/' )) )
81 /***********************************************************************
82 simple function to prune a pathname down to the basename of a file
83 **********************************************************************/
85 static char* dos_basename ( char *path
)
89 if ( !(p
= strrchr( path
, '\\' )) )
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 */
112 static int key_forms_fetch_values( const char *key
, REGVAL_CTR
*values
)
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",
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
;
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
);
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",
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
;
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();
184 char *base
, *new_path
;
185 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
186 fstring
*subkey_names
= NULL
;
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
) );
199 keystr
= remaining_path( key
+ strlen(KEY_CONTROL_PRINTERS
) );
203 /* enumerate all printers */
205 for (snum
=0; snum
<n_services
; snum
++) {
206 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
209 /* don't report the [printers] share */
211 if ( strequal( lp_servicename(snum
), PRINTERS_NAME
) )
214 fstrcpy( sname
, lp_servicename(snum
) );
216 regsubkey_ctr_addkey( subkeys
, sname
);
219 num_subkeys
= regsubkey_ctr_numkeys( subkeys
);
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
) ) )
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 */
240 SAFE_FREE( subkey_names
);
245 static BOOL
key_printer_store_keys( const char *key
, REGSUBKEY_CTR
*subkeys
)
250 static int key_printer_fetch_values( const char *key
, REGVAL_CTR
*values
)
253 char *keystr
, *key2
= NULL
;
254 char *base
, *new_path
;
255 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
256 NT_PRINTER_INFO_LEVEL_2
*info2
;
262 NT_PRINTER_DATA
*p_data
;
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
) );
281 keystr
= remaining_path( key
+ strlen(KEY_CONTROL_PRINTERS
) );
284 /* top level key has no values */
288 key2
= SMB_STRDUP( keystr
);
290 reg_split_path( keystr
, &base
, &new_path
);
292 fstrcpy( printername
, base
);
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
) ) )
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
;
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
);
394 /* now enumerate the key */
396 if ( !W_ERROR_IS_OK( get_a_printer(NULL
, &printer
, 2, printername
) ) )
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
));
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
) );
415 free_a_printer( &printer
, 2 );
422 static BOOL
key_printer_store_values( const char *key
, REGVAL_CTR
*values
)
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
[] = {
438 "Windows NT Alpha_AXP",
439 "Windows NT PowerPC",
443 fstring
*drivers
= NULL
;
444 int i
, env_index
, num_drivers
;
445 char *keystr
, *base
, *subkeypath
;
447 int num_subkeys
= -1;
448 int env_subkey_type
= 0;
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 */
458 for ( num_subkeys
=0; environments
[num_subkeys
]; num_subkeys
++ )
459 regsubkey_ctr_addkey( subkeys
, environments
[num_subkeys
] );
464 /* we are dealing with a subkey of "Environments */
466 pstrcpy( key2
, keystr
);
468 reg_split_path( keystr
, &base
, &subkeypath
);
472 for ( env_index
=0; environments
[env_index
]; env_index
++ ) {
473 if ( strequal( environments
[env_index
], base
) )
476 if ( !environments
[env_index
] )
479 /* ...\Print\Environements\...\ */
482 regsubkey_ctr_addkey( subkeys
, "Drivers" );
483 regsubkey_ctr_addkey( subkeys
, "Print Processors" );
488 /* more of the key path to process */
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
;
504 switch ( env_subkey_type
) {
505 case ENVIRONMENT_DRIVERS
:
506 switch ( env_index
) {
508 regsubkey_ctr_addkey( subkeys
, "Version-0" );
510 default: /* Windows NT based systems */
511 regsubkey_ctr_addkey( subkeys
, "Version-2" );
512 regsubkey_ctr_addkey( subkeys
, "Version-3" );
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 */
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" ) )
535 return !subkeypath
? 0 : -1;
538 /* only dealing with drivers from here on out */
540 version
= atoi(&base
[strlen(base
)-1]);
548 if ( version
!= 2 && version
!= 3 )
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",
570 static BOOL
key_driver_store_keys( const char *key
, REGSUBKEY_CTR
*subkeys
)
575 static int key_driver_fetch_values( const char *key
, REGVAL_CTR
*values
)
577 char *keystr
, *base
, *subkeypath
;
579 fstring arch_environment
;
582 NT_PRINTER_DRIVER_INFO_LEVEL driver_ctr
;
583 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
586 char *buffer2
= NULL
;
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
) );
601 /* The only keys below KEY_PRINTING\Environments is the
602 specific printer driver info */
606 pstrcpy( key2
, keystr
);
608 reg_split_path( keystr
, &base
, &subkeypath
);
611 fstrcpy( arch_environment
, base
);
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
;
629 /* for now bail out if we are seeing anything other than the drivers key */
631 if ( env_subkey_type
== ENVIRONMENT_PRINTPROC
)
635 reg_split_path( keystr
, &base
, &subkeypath
);
637 /* no values under Version-XX */
642 version
= atoi(&base
[strlen(base
)-1]);
644 /* printer driver name */
647 reg_split_path( keystr
, &base
, &subkeypath
);
648 /* don't go any deeper for now */
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
) )
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
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
) );
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 );
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 );
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
)
734 /**********************************************************************
735 Deal with the 'Print' key the same whether it came from SYSTEM
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
)) )
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
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
) ) )
771 static BOOL
key_ports_store_keys( const char *key
, REGSUBKEY_CTR
*subkeys
)
776 static int key_ports_fetch_values( const char *key
, REGVAL_CTR
*values
)
782 char *p
= remaining_path( key
+ strlen(KEY_PORTS
) );
784 /* no keys below ports */
788 if ( !W_ERROR_IS_OK(result
= enumports_hook( &numlines
, &lines
)) )
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
)
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 */
815 ®db_store_values
},
817 &key_forms_fetch_keys
,
819 &key_forms_fetch_values
,
821 { KEY_CONTROL_PRINTERS
,
822 &key_printer_fetch_keys
,
823 &key_printer_store_keys
,
824 &key_printer_fetch_values
,
825 &key_printer_store_values
},
827 &key_driver_fetch_keys
,
828 &key_driver_store_keys
,
829 &key_driver_fetch_values
,
830 &key_driver_store_values
},
832 &key_print_fetch_keys
,
836 { KEY_WINNT_PRINTERS
,
837 &key_printer_fetch_keys
,
838 &key_printer_store_keys
,
839 &key_printer_fetch_values
,
840 &key_printer_store_values
},
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
)
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 )
873 /**********************************************************************
874 *********************************************************************/
876 static int regprint_fetch_reg_keys( const char *key
, REGSUBKEY_CTR
*subkeys
)
878 int i
= match_registry_path( key
);
883 if ( !print_registry
[i
].fetch_subkeys
)
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
);
899 if ( !print_registry
[i
].store_subkeys
)
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
);
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
)
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
);
934 if ( !print_registry
[i
].store_values
)
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
,