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 );
52 /*********************************************************************
53 *********************************************************************
55 *********************************************************************
56 *********************************************************************/
59 /**********************************************************************
60 move to next non-delimter character
61 *********************************************************************/
63 static char* remaining_path( const char *key )
65 static pstring new_path;
71 pstrcpy( new_path, key );
72 /* normalize_reg_path( new_path ); */
74 if ( !(p = strchr( new_path, '\\' )) )
76 if ( !(p = strchr( new_path, '/' )) )
87 /***********************************************************************
88 simple function to prune a pathname down to the basename of a file
89 **********************************************************************/
91 static char* dos_basename ( char *path )
95 if ( !(p = strrchr( path, '\\' )) )
103 /*********************************************************************
104 *********************************************************************
105 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/FORMS"
106 *********************************************************************
107 *********************************************************************/
109 static int key_forms_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
111 char *p = remaining_path( key + strlen(KEY_FORMS) );
113 /* no keys below Forms */
121 /**********************************************************************
122 *********************************************************************/
124 static int key_forms_fetch_values( const char *key, REGVAL_CTR *values )
127 int i, num_values, form_index = 1;
128 nt_forms_struct *forms_list = NULL;
129 nt_forms_struct *form;
131 DEBUG(10,("print_values_forms: key=>[%s]\n", key ? key : "NULL" ));
133 num_values = get_ntforms( &forms_list );
135 DEBUG(10,("hive_forms_fetch_values: [%d] user defined forms returned\n",
138 /* handle user defined forms */
140 for ( i=0; i<num_values; i++ ) {
141 form = &forms_list[i];
143 data[0] = form->width;
144 data[1] = form->length;
145 data[2] = form->left;
147 data[4] = form->right;
148 data[5] = form->bottom;
149 data[6] = form_index++;
150 data[7] = form->flag;
152 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );
155 SAFE_FREE( forms_list );
158 /* handle built-on forms */
160 num_values = get_builtin_ntforms( &forms_list );
162 DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n",
165 for ( i=0; i<num_values; i++ ) {
166 form = &forms_list[i];
168 data[0] = form->width;
169 data[1] = form->length;
170 data[2] = form->left;
172 data[4] = form->right;
173 data[5] = form->bottom;
174 data[6] = form_index++;
175 data[7] = form->flag;
177 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );
180 SAFE_FREE( forms_list );
182 return regval_ctr_numvals( values );
185 /*********************************************************************
186 *********************************************************************
187 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS"
188 ** "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
189 *********************************************************************
190 *********************************************************************/
192 /*********************************************************************
193 strip off prefix for printers key. DOes return a pointer to static
195 *********************************************************************/
197 static char* strip_printers_prefix( const char *key )
202 pstrcpy( path, key );
203 normalize_reg_path( path );
205 /* normalizing the path does not change length, just key delimiters and case */
207 if ( strncmp( path, KEY_WINNT_PRINTERS, strlen(KEY_WINNT_PRINTERS) ) == 0 )
208 subkeypath = remaining_path( key + strlen(KEY_WINNT_PRINTERS) );
210 subkeypath = remaining_path( key + strlen(KEY_CONTROL_PRINTERS) );
215 /*********************************************************************
216 *********************************************************************/
218 static int key_printers_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
220 int n_services = lp_numservices();
226 char *printername, *printerdatakey;
227 NT_PRINTER_INFO_LEVEL *printer = NULL;
228 fstring *subkey_names = NULL;
230 DEBUG(10,("key_printers_fetch_keys: key=>[%s]\n", key ? key : "NULL" ));
232 printers_key = strip_printers_prefix( key );
234 if ( !printers_key ) {
235 /* enumerate all printers */
237 for (snum=0; snum<n_services; snum++) {
238 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
241 /* don't report the [printers] share */
243 if ( strequal( lp_servicename(snum), PRINTERS_NAME ) )
246 fstrcpy( sname, lp_servicename(snum) );
248 regsubkey_ctr_addkey( subkeys, sname );
251 num_subkeys = regsubkey_ctr_numkeys( subkeys );
255 /* get information for a specific printer */
257 reg_split_path( printers_key, &printername, &printerdatakey );
259 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
262 num_subkeys = get_printer_subkeys( &printer->info_2->data, printerdatakey?printerdatakey:"", &subkey_names );
264 for ( i=0; i<num_subkeys; i++ )
265 regsubkey_ctr_addkey( subkeys, subkey_names[i] );
267 free_a_printer( &printer, 2 );
269 /* no other subkeys below here */
272 SAFE_FREE( subkey_names );
277 /**********************************************************************
278 *********************************************************************/
280 static BOOL add_printers_by_registry( REGSUBKEY_CTR *subkeys )
285 /**********************************************************************
286 *********************************************************************/
288 static BOOL key_printers_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
291 char *printername, *printerdatakey;
292 NT_PRINTER_INFO_LEVEL *printer = NULL;
296 printers_key = strip_printers_prefix( key );
298 if ( !printers_key ) {
299 /* have to deal with some new or deleted printer */
300 return add_printers_by_registry( subkeys );
303 reg_split_path( printers_key, &printername, &printerdatakey );
305 /* lookup the printer */
307 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, printername)) ) {
308 DEBUG(0,("key_printers_store_keys: Tried to store subkey for bad printername %s\n",
313 num_subkeys = regsubkey_ctr_numkeys( subkeys );
314 for ( i=0; i<num_subkeys; i++ ) {
315 subkeyname = regsubkey_ctr_specific_key(subkeys, i);
316 /* add any missing printer keys */
317 if ( lookup_printerkey(&printer->info_2->data, subkeyname) == -1 ) {
318 if ( add_new_printer_key( &printer->info_2->data, subkeyname ) == -1 )
323 /* write back to disk */
325 mod_a_printer( printer, 2 );
330 free_a_printer( &printer, 2 );
335 /**********************************************************************
336 *********************************************************************/
338 static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *values )
345 uint32 printer_status = PRINTER_STATUS_OK;
348 regval_ctr_addvalue( values, "Attributes", REG_DWORD, (char*)&info2->attributes, sizeof(info2->attributes) );
349 regval_ctr_addvalue( values, "Priority", REG_DWORD, (char*)&info2->priority, sizeof(info2->attributes) );
350 regval_ctr_addvalue( values, "ChangeID", REG_DWORD, (char*)&info2->changeid, sizeof(info2->changeid) );
351 regval_ctr_addvalue( values, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) );
353 /* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */
354 regval_ctr_addvalue( values, "Status", REG_DWORD, (char*)&printer_status, sizeof(info2->status) );
356 regval_ctr_addvalue( values, "StartTime", REG_DWORD, (char*)&info2->starttime, sizeof(info2->starttime) );
357 regval_ctr_addvalue( values, "UntilTime", REG_DWORD, (char*)&info2->untiltime, sizeof(info2->untiltime) );
359 /* strip the \\server\ from this string */
360 if ( !(p = strrchr( info2->printername, '\\' ) ) )
361 p = info2->printername;
364 init_unistr2( &data, p, UNI_STR_TERMINATE);
365 regval_ctr_addvalue( values, "Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
367 init_unistr2( &data, info2->location, UNI_STR_TERMINATE);
368 regval_ctr_addvalue( values, "Location", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
370 init_unistr2( &data, info2->comment, UNI_STR_TERMINATE);
371 regval_ctr_addvalue( values, "Description", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
373 init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE);
374 regval_ctr_addvalue( values, "Parameters", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
376 init_unistr2( &data, info2->portname, UNI_STR_TERMINATE);
377 regval_ctr_addvalue( values, "Port", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
379 init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE);
380 regval_ctr_addvalue( values, "Share Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
382 init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE);
383 regval_ctr_addvalue( values, "Printer Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
385 init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE);
386 regval_ctr_addvalue( values, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
388 init_unistr2( &data, "WinPrint", UNI_STR_TERMINATE);
389 regval_ctr_addvalue( values, "Print Processor", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
391 init_unistr2( &data, "RAW", UNI_STR_TERMINATE);
392 regval_ctr_addvalue( values, "Datatype", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
395 /* use a prs_struct for converting the devmode and security
396 descriptor to REG_BINARY */
398 prs_init( &prs, MAX_PDU_FRAG_LEN, regval_ctr_getctx(values), MARSHALL);
400 /* stream the device mode */
402 snum = lp_servicenumber(info2->sharename);
403 if ( (devmode = construct_dev_mode( snum )) != NULL ) {
404 if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
405 offset = prs_offset( &prs );
406 regval_ctr_addvalue( values, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
410 prs_mem_clear( &prs );
411 prs_set_offset( &prs, 0 );
413 /* stream the printer security descriptor */
415 if ( info2->secdesc_buf && info2->secdesc_buf->len ) {
416 if ( sec_io_desc("sec_desc", &info2->secdesc_buf->sec, &prs, 0 ) ) {
417 offset = prs_offset( &prs );
418 regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&prs), offset );
422 prs_mem_free( &prs );
427 /**********************************************************************
428 *********************************************************************/
430 static int key_printers_fetch_values( const char *key, REGVAL_CTR *values )
434 char *printername, *printerdatakey;
435 NT_PRINTER_INFO_LEVEL *printer = NULL;
436 NT_PRINTER_DATA *p_data;
439 printers_key = strip_printers_prefix( key );
441 /* top level key values stored in the registry has no values */
443 if ( !printers_key ) {
444 /* normalize to the 'HKLM\SOFTWARE\...\Print\Printers' ket */
445 return regdb_fetch_values( KEY_WINNT_PRINTERS, values );
448 /* lookup the printer object */
450 reg_split_path( printers_key, &printername, &printerdatakey );
451 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
454 if ( !printerdatakey ) {
455 fill_in_printer_values( printer->info_2, values );
459 /* iterate over all printer data keys and fill the regval container */
461 p_data = &printer->info_2->data;
462 if ( (key_index = lookup_printerkey( p_data, printerdatakey )) == -1 ) {
463 /* failure....should never happen if the client has a valid open handle first */
464 DEBUG(10,("key_printers_fetch_values: Unknown keyname [%s]\n", printerdatakey));
466 free_a_printer( &printer, 2 );
470 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
471 for ( i=0; i<num_values; i++ )
472 regval_ctr_copyvalue( values, regval_ctr_specific_value(&p_data->keys[key_index].values, i) );
477 free_a_printer( &printer, 2 );
479 return regval_ctr_numvals( values );
482 /**********************************************************************
483 *********************************************************************/
485 static BOOL key_printers_store_values( const char *key, REGVAL_CTR *values )
489 printers_key = strip_printers_prefix( key );
491 /* values in the top level key get stored in the registry */
493 if ( !printers_key ) {
494 /* normalize on thw 'HKLM\SOFTWARE\....\Print\Printers' ket */
495 return regdb_store_values( KEY_WINNT_PRINTERS, values );
501 /*********************************************************************
502 *********************************************************************
503 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS"
504 *********************************************************************
505 *********************************************************************/
507 static int key_driver_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
509 const char *environments[] = {
513 "Windows NT Alpha_AXP",
514 "Windows NT PowerPC",
518 fstring *drivers = NULL;
519 int i, env_index, num_drivers;
520 char *keystr, *base, *subkeypath;
522 int num_subkeys = -1;
525 DEBUG(10,("key_driver_fetch_keys key=>[%s]\n", key ? key : "NULL" ));
527 keystr = remaining_path( key + strlen(KEY_ENVIRONMENTS) );
529 /* list all possible architectures */
532 for ( num_subkeys=0; environments[num_subkeys]; num_subkeys++ )
533 regsubkey_ctr_addkey( subkeys, environments[num_subkeys] );
538 /* we are dealing with a subkey of "Environments */
540 pstrcpy( key2, keystr );
542 reg_split_path( keystr, &base, &subkeypath );
546 for ( env_index=0; environments[env_index]; env_index++ ) {
547 if ( strequal( environments[env_index], base ) )
550 if ( !environments[env_index] )
553 /* ...\Print\Environements\...\ */
556 regsubkey_ctr_addkey( subkeys, "Drivers" );
557 regsubkey_ctr_addkey( subkeys, "Print Processors" );
562 /* more of the key path to process */
565 reg_split_path( keystr, &base, &subkeypath );
567 /* ...\Print\Environements\...\Drivers\ */
570 if ( strequal(base, "Drivers") ) {
571 switch ( env_index ) {
573 regsubkey_ctr_addkey( subkeys, "Version-0" );
575 default: /* Windows NT based systems */
576 regsubkey_ctr_addkey( subkeys, "Version-2" );
577 regsubkey_ctr_addkey( subkeys, "Version-3" );
581 return regsubkey_ctr_numkeys( subkeys );
582 } else if ( strequal(base, "Print Processors") ) {
583 if ( env_index == 1 || env_index == 5 || env_index == 6 )
584 regsubkey_ctr_addkey( subkeys, "winprint" );
586 return regsubkey_ctr_numkeys( subkeys );
588 return -1; /* bad path */
591 /* we finally get to enumerate the drivers */
593 /* only one possible subkey below PrintProc key */
595 if ( strequal(base, "Print Processors") ) {
597 reg_split_path( keystr, &base, &subkeypath );
599 /* no subkeys below this point */
604 /* only allow one keyname here -- 'winprint' */
606 return strequal( base, "winprint" ) ? 0 : -1;
609 /* only dealing with drivers from here on out */
612 reg_split_path( keystr, &base, &subkeypath );
613 version = atoi(&base[strlen(base)-1]);
621 if ( version != 2 && version != 3 )
628 num_drivers = get_ntdrivers( &drivers, environments[env_index], version );
629 for ( i=0; i<num_drivers; i++ )
630 regsubkey_ctr_addkey( subkeys, drivers[i] );
632 return regsubkey_ctr_numkeys( subkeys );
635 /* if anything else left, just say if has no subkeys */
637 DEBUG(1,("key_driver_fetch_keys unhandled key [%s] (subkey == %s\n",
644 /**********************************************************************
645 *********************************************************************/
647 static void fill_in_driver_values( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3, REGVAL_CTR *values )
650 char *buffer2 = NULL;
656 filename = dos_basename( info3->driverpath );
657 init_unistr2( &data, filename, UNI_STR_TERMINATE);
658 regval_ctr_addvalue( values, "Driver", REG_SZ, (char*)data.buffer,
659 data.uni_str_len*sizeof(uint16) );
661 filename = dos_basename( info3->configfile );
662 init_unistr2( &data, filename, UNI_STR_TERMINATE);
663 regval_ctr_addvalue( values, "Configuration File", REG_SZ, (char*)data.buffer,
664 data.uni_str_len*sizeof(uint16) );
666 filename = dos_basename( info3->datafile );
667 init_unistr2( &data, filename, UNI_STR_TERMINATE);
668 regval_ctr_addvalue( values, "Data File", REG_SZ, (char*)data.buffer,
669 data.uni_str_len*sizeof(uint16) );
671 filename = dos_basename( info3->helpfile );
672 init_unistr2( &data, filename, UNI_STR_TERMINATE);
673 regval_ctr_addvalue( values, "Help File", REG_SZ, (char*)data.buffer,
674 data.uni_str_len*sizeof(uint16) );
676 init_unistr2( &data, info3->defaultdatatype, UNI_STR_TERMINATE);
677 regval_ctr_addvalue( values, "Data Type", REG_SZ, (char*)data.buffer,
678 data.uni_str_len*sizeof(uint16) );
680 regval_ctr_addvalue( values, "Version", REG_DWORD, (char*)&info3->cversion,
681 sizeof(info3->cversion) );
683 if ( info3->dependentfiles ) {
684 /* place the list of dependent files in a single
685 character buffer, separating each file name by
688 for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ ) {
689 /* strip the path to only the file's base name */
691 filename = dos_basename( info3->dependentfiles[i] );
693 length = strlen(filename);
695 buffer2 = SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
700 init_unistr2( &data, filename, UNI_STR_TERMINATE);
701 memcpy( buffer+buffer_size, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
703 buffer_size += (length + 1)*sizeof(uint16);
706 /* terminated by double NULL. Add the final one here */
708 buffer2 = SMB_REALLOC( buffer, buffer_size + 2 );
714 buffer[buffer_size++] = '\0';
715 buffer[buffer_size++] = '\0';
719 regval_ctr_addvalue( values, "Dependent Files", REG_MULTI_SZ, buffer, buffer_size );
726 /**********************************************************************
727 *********************************************************************/
729 static int driver_arch_fetch_values( char *key, REGVAL_CTR *values )
731 char *keystr, *base, *subkeypath;
732 fstring arch_environment;
735 NT_PRINTER_DRIVER_INFO_LEVEL driver_ctr;
738 reg_split_path( key, &base, &subkeypath );
740 /* no values in 'Environments\Drivers\Windows NT x86' */
745 /* We have the Architecture string and some subkey name:
746 Currently we only support
749 Anything else is an error.
752 fstrcpy( arch_environment, base );
755 reg_split_path( keystr, &base, &subkeypath );
757 if ( strequal(base, "Print Processors") )
760 /* only Drivers key can be left */
762 if ( !strequal(base, "Drivers") )
768 /* We know that we have Architechure\Drivers with some subkey name
769 The subkey name has to be Version-XX */
772 reg_split_path( keystr, &base, &subkeypath );
777 version = atoi(&base[strlen(base)-1]);
779 /* BEGIN PRINTER DRIVER NAME BLOCK */
782 reg_split_path( keystr, &base, &subkeypath );
784 /* don't go any deeper for now */
786 fstrcpy( driver, base );
788 w_result = get_a_printer_driver( &driver_ctr, 3, driver, arch_environment, version );
790 if ( !W_ERROR_IS_OK(w_result) )
793 fill_in_driver_values( driver_ctr.info_3, values );
795 free_a_printer_driver( driver_ctr, 3 );
797 /* END PRINTER DRIVER NAME BLOCK */
800 DEBUG(8,("key_driver_fetch_values: Exit\n"));
802 return regval_ctr_numvals( values );
805 /**********************************************************************
806 *********************************************************************/
808 static int key_driver_fetch_values( const char *key, REGVAL_CTR *values )
813 DEBUG(8,("key_driver_fetch_values: Enter key => [%s]\n", key ? key : "NULL"));
815 /* no values in the Environments key */
817 if ( !(keystr = remaining_path( key + strlen(KEY_ENVIRONMENTS) )) )
820 pstrcpy( subkey, keystr);
822 /* pass off to handle subkeys */
824 return driver_arch_fetch_values( subkey, values );
827 /*********************************************************************
828 *********************************************************************
829 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT"
830 *********************************************************************
831 *********************************************************************/
833 static int key_print_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
835 int key_len = strlen(key);
837 /* no keys below 'Print' handled here */
839 if ( (key_len != strlen(KEY_CONTROL_PRINT)) && (key_len != strlen(KEY_WINNT_PRINT)) )
842 regsubkey_ctr_addkey( subkeys, "Environments" );
843 regsubkey_ctr_addkey( subkeys, "Monitors" );
844 regsubkey_ctr_addkey( subkeys, "Forms" );
845 regsubkey_ctr_addkey( subkeys, "Printers" );
847 return regsubkey_ctr_numkeys( subkeys );
850 /**********************************************************************
851 *********************************************************************
852 ** Structure to hold dispatch table of ops for various printer keys.
853 ** Make sure to always store deeper keys along the same path first so
854 ** we ge a more specific match.
855 *********************************************************************
856 *********************************************************************/
858 static struct reg_dyn_tree print_registry[] = {
859 /* just pass the monitor onto the registry tdb */
864 ®db_store_values },
866 &key_forms_fetch_keys,
868 &key_forms_fetch_values,
870 { KEY_CONTROL_PRINTERS,
871 &key_printers_fetch_keys,
872 &key_printers_store_keys,
873 &key_printers_fetch_values,
874 &key_printers_store_values },
876 &key_driver_fetch_keys,
878 &key_driver_fetch_values,
881 &key_print_fetch_keys,
885 { KEY_WINNT_PRINTERS,
886 &key_printers_fetch_keys,
887 &key_printers_store_keys,
888 &key_printers_fetch_values,
889 &key_printers_store_values },
894 ®db_store_values },
896 { NULL, NULL, NULL, NULL, NULL }
900 /**********************************************************************
901 *********************************************************************
902 ** Main reg_printing interface functions
903 *********************************************************************
904 *********************************************************************/
906 /***********************************************************************
907 Lookup a key in the print_registry table, returning its index.
909 **********************************************************************/
911 static int match_registry_path( const char *key )
919 pstrcpy( path, key );
920 normalize_reg_path( path );
922 for ( i=0; print_registry[i].path; i++ ) {
923 if ( strncmp( path, print_registry[i].path, strlen(print_registry[i].path) ) == 0 )
930 /***********************************************************************
931 **********************************************************************/
933 static int regprint_fetch_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
935 int i = match_registry_path( key );
940 if ( !print_registry[i].fetch_subkeys )
943 return print_registry[i].fetch_subkeys( key, subkeys );
946 /**********************************************************************
947 *********************************************************************/
949 static BOOL regprint_store_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
951 int i = match_registry_path( key );
956 if ( !print_registry[i].store_subkeys )
959 return print_registry[i].store_subkeys( key, subkeys );
962 /**********************************************************************
963 *********************************************************************/
965 static int regprint_fetch_reg_values( const char *key, REGVAL_CTR *values )
967 int i = match_registry_path( key );
972 /* return 0 values by default since we know the key had
973 to exist because the client opened a handle */
975 if ( !print_registry[i].fetch_values )
978 return print_registry[i].fetch_values( key, values );
981 /**********************************************************************
982 *********************************************************************/
984 static BOOL regprint_store_reg_values( const char *key, REGVAL_CTR *values )
986 int i = match_registry_path( key );
991 if ( !print_registry[i].store_values )
994 return print_registry[i].store_values( key, values );
998 * Table of function pointers for accessing printing data
1001 REGISTRY_OPS printing_ops = {
1002 regprint_fetch_reg_keys,
1003 regprint_fetch_reg_values,
1004 regprint_store_reg_keys,
1005 regprint_store_reg_values,