several changes in this checkin
authorGerald Carter <jerry@samba.org>
Wed, 24 Jul 2002 06:42:09 +0000 (06:42 +0000)
committerGerald Carter <jerry@samba.org>
Wed, 24 Jul 2002 06:42:09 +0000 (06:42 +0000)
* added REG_OPEN_HKCR for supporting regedit.exe

* All data n a REGISTRY_VALUE is stored to a pointer now

* fixed REG_INFO to correctly display data when double clicking on
  and entry in the registry editor

* Will now enumerate installed driver_info_3 data

* fixed numerous bugs related to pointer offsets, memory issues, etc..
  in the registry routines

* added a simple caching mechanism to fetch_reg_[keys|values]_specific()

All that is left now is to enumerate PrinterData and I will have finished
what I started out to do....

source/include/rpc_reg.h
source/registry/reg_db.c
source/registry/reg_frontend.c
source/registry/reg_printing.c
source/rpc_parse/parse_reg.c
source/rpc_server/srv_reg.c
source/rpc_server/srv_reg_nt.c

index d025cb2c0d86467f0b901f0c0c7f6a710e1e2726..e2347c328be8721df74a01e2e276d3e2f73c3558 100644 (file)
@@ -26,7 +26,6 @@
 
 /* winreg pipe defines 
    NOT IMPLEMENTED !!
-#define REG_OPEN_HKCR          0x00
 #define _REG_UNK_01            0x01
 #define _REG_UNK_03            0x03
 #define REG_CREATE_KEY         0x06
@@ -45,6 +44,7 @@
 */
 
 /* Implemented */
+#define REG_OPEN_HKCR          0x00
 #define REG_OPEN_HKLM          0x02
 #define REG_OPEN_HKU           0x04
 #define REG_CLOSE              0x05
@@ -65,6 +65,7 @@
 
 #define KEY_HKLM       "HKLM"
 #define KEY_HKU                "HKU"
+#define KEY_HKCR       "HKCR"
 #define KEY_PRINTING   "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print"
 #define KEY_TREE_ROOT  ""
 
@@ -93,12 +94,16 @@ typedef struct {
        fstring         valuename;
        uint16          type;
        uint32          size;   /* in bytes */
+       void            *data_p;
+#if 0
        union {
                char    *string;
-               uint32  dword;
+               uint32  *dword;
                uint8   *binary;
                void    *void_ptr;      /* for casting only */
        } data;
+#endif
+
 } REGISTRY_VALUE;
 
 /* container for regostry values */
@@ -145,7 +150,7 @@ typedef struct _RegistryKey {
        struct _RegistryKey *prev, *next;
 
        POLICY_HND      hnd;
-       fstring         name;   /* full name of registry key */
+       pstring         name;   /* full name of registry key */
        REGISTRY_HOOK   *hook;
        
 } REGISTRY_KEY;
@@ -551,7 +556,7 @@ typedef struct r_reg_info_info
        uint32 type;            /* key datatype  */
 
        uint32 ptr_uni_val;     /* key value pointer */
-       BUFFER2 *uni_val;       /* key value */
+       BUFFER2 uni_val;        /* key value */
 
        uint32 ptr_max_len;
        uint32 buf_max_len;
index 714e14e48bad2d691a41bb505b4b02bbccc6a25d..773a4f7fb5bd8e5b96b93c10b987f5d78fbd1d1d 100644 (file)
@@ -106,6 +106,12 @@ static BOOL init_registry_data( void )
        if ( !regdb_store_reg_keys( keyname, &subkeys ) )
                return False;
                
+       /* HKEY_CLASSES_ROOT*/
+               
+       pstrcpy( keyname, KEY_HKCR );
+       if ( !regdb_store_reg_keys( keyname, &subkeys ) )
+               return False;
+               
        return True;
 }
 
@@ -233,6 +239,7 @@ int regdb_fetch_reg_keys( char* key, REGSUBKEY_CTR *ctr )
        int i;
        fstring subkeyname;
 
+       DEBUG(10,("regdb_fetch_reg_keys: Enter key => [%s]\n", key ? key : "NULL"));
        
        pstrcpy( path, key );
        
@@ -258,6 +265,8 @@ int regdb_fetch_reg_keys( char* key, REGSUBKEY_CTR *ctr )
 
        SAFE_FREE( dbuf.dptr );
        
+       DEBUG(10,("regdb_fetch_reg_keys: Exit [%d] items\n", num_items));
+       
        return num_items;
 }
 
index a2822073765e06c773dbbc4aa9c6b11a602d2ec4..db612709d10bffdd94c0f944e8915a3272444863 100644 (file)
@@ -149,7 +149,6 @@ int regval_ctr_numvals( REGVAL_CTR *ctr )
 REGISTRY_VALUE* dup_registry_value( REGISTRY_VALUE *val )
 {
        REGISTRY_VALUE  *copy = NULL;
-       BOOL            fail = True;
        
        if ( !val )
                return NULL;
@@ -162,35 +161,15 @@ REGISTRY_VALUE* dup_registry_value( REGISTRY_VALUE *val )
        /* copy all the non-pointer initial data */
        
        memcpy( copy, val, sizeof(REGISTRY_VALUE) );
+       if ( val->data_p ) 
+       {
+               if ( !(copy->data_p = memdup( val->data_p, val->size )) ) {
+                       DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n",
+                               val->size));
+                       SAFE_FREE( copy );
+               }
+       }
        
-       switch ( val->type ) {
-               case REG_SZ:
-                       if ( !(copy->data.string = strdup( val->data.string )) ) {
-                               DEBUG(0,("dup_registry_value: strdup() failed for [%s]!\n",
-                                       val->data.string));
-                               goto done;
-                       }
-                       break;
-                       
-               case REG_DWORD:
-                       /* nothing to be done; already copied by memcpy() */
-                       break;
-                       
-               case REG_BINARY:
-                       if ( !(copy->data.string = memdup( val->data.binary, val->size )) ) {
-                               DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n",
-                                       val->size));
-                               goto done;
-                       }
-                       break;
-        } 
-        
-        fail = False;
-        
-done:
-       if ( fail )
-               SAFE_FREE( copy );
-
        return copy;    
 }
 
@@ -203,16 +182,7 @@ void free_registry_value( REGISTRY_VALUE *val )
        if ( !val )
                return;
                
-       switch ( val->type ) 
-       {
-               case REG_SZ:
-                       SAFE_FREE( val->data.string );
-                       break;
-               case REG_BINARY:
-                       SAFE_FREE( val->data.binary );
-                       break;
-       }
-       
+       SAFE_FREE( val->data_p );
        SAFE_FREE( val );
        
        return;
@@ -263,19 +233,26 @@ int regval_ctr_addvalue( REGVAL_CTR *ctr, char *name, uint16 type,
        
                fstrcpy( ctr->values[ctr->num_values]->valuename, name );
                ctr->values[ctr->num_values]->type = type;
+               ctr->values[ctr->num_values]->data_p = talloc_memdup( ctr->ctx, data_p, size );
+               ctr->values[ctr->num_values]->size = size;
+#if 0
                switch ( type )
                {
                        case REG_SZ:
                                ctr->values[ctr->num_values]->data.string = talloc_strdup( ctr->ctx, data_p );
                                break;
+                       case REG_MULTI_SZ:
+                               ctr->values[ctr->num_values]->data.string = talloc_memdup( ctr->ctx, data_p, size );
+                               break;
                        case REG_DWORD:
+                               ctr->values[ctr->num_values]->data.dword = *(uint32*)data_p;
                                break;
                        case REG_BINARY:
                                ctr->values[ctr->num_values]->data.binary = talloc_memdup( ctr->ctx, data_p, size );
                                break;
                                
                }
-               ctr->values[ctr->num_values]->size = size;
+#endif
                
                ctr->num_values++;
        }
@@ -374,23 +351,46 @@ int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
 
 BOOL fetch_reg_keys_specific( REGISTRY_KEY *key, char** subkey, uint32 key_index )
 {
+       static REGSUBKEY_CTR ctr;
+       static pstring save_path;
+       static BOOL ctr_init = False;
        char *s;
-       REGSUBKEY_CTR ctr;
        
-       ZERO_STRUCTP( &ctr );
+       *subkey = NULL;
        
-       regsubkey_ctr_init( &ctr );
+       /* simple caching for performance; very basic heuristic */
        
-       if ( fetch_reg_keys( key, &ctr) == -1 )
-               return False;
+       if ( !ctr_init ) {
+               DEBUG(8,("fetch_reg_keys_specific: Initializing cache of subkeys for [%s]\n", key->name));
+               ZERO_STRUCTP( &ctr );   
+               regsubkey_ctr_init( &ctr );
+               
+               pstrcpy( save_path, key->name );
+               
+               if ( fetch_reg_keys( key, &ctr) == -1 )
+                       return False;
+                       
+               ctr_init = True;
+       }
+       /* clear the cache when key_index == 0 or the path has changed */
+       else if ( !key_index || StrCaseCmp( save_path, key->name) ) {
 
+               DEBUG(8,("fetch_reg_keys_specific: Updating cache of subkeys for [%s]\n", key->name));
+               
+               regsubkey_ctr_destroy( &ctr );  
+               regsubkey_ctr_init( &ctr );
+               
+               pstrcpy( save_path, key->name );
+               
+               if ( fetch_reg_keys( key, &ctr) == -1 )
+                       return False;
+       }
+       
        if ( !(s = regsubkey_ctr_specific_key( &ctr, key_index )) )
                return False;
 
        *subkey = strdup( s );
 
-       regsubkey_ctr_destroy( &ctr ); 
-       
        return True;
 }
 
@@ -416,25 +416,49 @@ int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
  responsible for freeing memory
  ***********************************************************************/
 
-BOOL fetch_reg_values_specific( REGISTRY_KEY *key, REGISTRY_VALUE **val, uint32 key_index )
+BOOL fetch_reg_values_specific( REGISTRY_KEY *key, REGISTRY_VALUE **val, uint32 val_index )
 {
-       REGVAL_CTR      ctr;
-       REGISTRY_VALUE  *v;
+       static REGVAL_CTR       ctr;
+       static pstring          save_path;
+       static BOOL             ctr_init = False;
+       REGISTRY_VALUE          *v;
        
-       ZERO_STRUCTP( &ctr );
+       *val = NULL;
        
-       regval_ctr_init( &ctr );
+       /* simple caching for performance; very basic heuristic */
        
-       if ( fetch_reg_values( key, &ctr) == -1 )
-               return False;
+       if ( !ctr_init ) {
+               DEBUG(8,("fetch_reg_values_specific: Initializing cache of values for [%s]\n", key->name));
 
-       if ( !(v = regval_ctr_specific_value( &ctr, key_index )) )
+               ZERO_STRUCTP( &ctr );   
+               regval_ctr_init( &ctr );
+               
+               pstrcpy( save_path, key->name );
+               
+               if ( fetch_reg_values( key, &ctr) == -1 )
+                       return False;
+                       
+               ctr_init = True;
+       }
+       /* clear the cache when val_index == 0 or the path has changed */
+       else if ( !val_index || StrCaseCmp(save_path, key->name) ) {
+
+               DEBUG(8,("fetch_reg_values_specific: Updating cache of values for [%s]\n", key->name));         
+               
+               regval_ctr_destroy( &ctr );     
+               regval_ctr_init( &ctr );
+               
+               pstrcpy( save_path, key->name );
+               
+               if ( fetch_reg_values( key, &ctr) == -1 )
+                       return False;
+       }
+       
+       if ( !(v = regval_ctr_specific_value( &ctr, val_index )) )
                return False;
 
        *val = dup_registry_value( v );
 
-       regval_ctr_destroy( &ctr ); 
-       
        return True;
 }
 
index f4c1feb281f72436da30b50cb8c5a5aae99a0bab..d8e0f18953c6b7ec39998d40b775b7764d7c30d3 100644 (file)
@@ -84,18 +84,270 @@ static char* trim_reg_path( char *path )
  
 static int print_subpath_environments( char *key, REGSUBKEY_CTR *subkeys )
 {
+       char *environments[] = {
+               "Windows 4.0",
+               "Windows NT x86",
+               "Windows NT R4000",
+               "Windows NT Alpha_AXP",
+               "Windows NT PowerPC",
+               NULL };
+       fstring *drivers = NULL;
+       int i, env_index, num_drivers;
+       BOOL valid_env = False;
+       char *base, *new_path;
+       char *keystr;
+       char *key2 = NULL;
+       int num_subkeys = -1;
+
        DEBUG(10,("print_subpath_environments: key=>[%s]\n", key ? key : "NULL" ));
        
+       /* listed architectures of installed drivers */
+       
+       if ( !key ) 
+       {
+               /* Windows 9x drivers */
+               
+               if ( get_ntdrivers( &drivers, environments[0], 0 ) )
+                       regsubkey_ctr_addkey( subkeys,  environments[0] );
+               SAFE_FREE( drivers );
+                                       
+               /* Windows NT/2k intel drivers */
+               
+               if ( get_ntdrivers( &drivers, environments[1], 2 ) 
+                       || get_ntdrivers( &drivers, environments[1], 3 ) )
+               {
+                       regsubkey_ctr_addkey( subkeys,  environments[1] );
+               }
+               SAFE_FREE( drivers );
+               
+               /* Windows NT 4.0; non-intel drivers */
+               for ( i=2; environments[i]; i++ ) {
+                       if ( get_ntdrivers( &drivers, environments[i], 2 ) )
+                               regsubkey_ctr_addkey( subkeys,  environments[i] );
+               
+               }
+               SAFE_FREE( drivers );
+
+               num_subkeys = regsubkey_ctr_numkeys( subkeys ); 
+               goto done;
+       }
+       
+       /* we are dealing with a subkey of "Environments */
+       
+       key2 = strdup( key );
+       keystr = key2;
+       reg_split_path( keystr, &base, &new_path );
+       
+       /* sanity check */
+       
+       for ( env_index=0; environments[env_index]; env_index++ ) {
+               if ( StrCaseCmp( environments[env_index], base ) == 0 ) {
+                       valid_env = True;
+                       break;
+               }
+       }
+               
+       if ( !valid_env )
+               return -1;
+
+       /* enumerate driver versions; environment is environments[env_index] */
+       
+       if ( !new_path ) {
+               switch ( env_index ) {
+                       case 0: /* Win9x */
+                               if ( get_ntdrivers( &drivers, environments[0], 0 ) ) {
+                                       regsubkey_ctr_addkey( subkeys, "0" );
+                                       SAFE_FREE( drivers );
+                               }
+                               break;
+                       case 1: /* Windows NT/2k - intel */
+                               if ( get_ntdrivers( &drivers, environments[1], 2 ) ) {
+                                       regsubkey_ctr_addkey( subkeys, "2" );
+                                       SAFE_FREE( drivers );
+                               }
+                               if ( get_ntdrivers( &drivers, environments[1], 3 ) ) {
+                                       regsubkey_ctr_addkey( subkeys, "3" );
+                                       SAFE_FREE( drivers );
+                               }
+                               break;
+                       default: /* Windows NT - nonintel */
+                               if ( get_ntdrivers( &drivers, environments[env_index], 2 ) ) {
+                                       regsubkey_ctr_addkey( subkeys, "2" );
+                                       SAFE_FREE( drivers );
+                               }
+                       
+               }
+               
+               num_subkeys = regsubkey_ctr_numkeys( subkeys ); 
+               goto done;
+       }
+       
+       /* we finally get to enumerate the drivers */
+       
+       keystr = new_path;
+       reg_split_path( keystr, &base, &new_path );
+       
+       if ( !new_path ) {
+               num_drivers = get_ntdrivers( &drivers, environments[env_index], atoi(base) );
+               for ( i=0; i<num_drivers; i++ )
+                       regsubkey_ctr_addkey( subkeys, drivers[i] );
+                       
+               num_subkeys = regsubkey_ctr_numkeys( subkeys ); 
+               goto done;
+       }
+       
+done:
+       SAFE_FREE( key2 );
+               
+       return num_subkeys;
+}
+
+/***********************************************************************
+ simple function to prune a pathname down to the basename of a file 
+ **********************************************************************/
+static char* dos_basename ( char *path )
+{
+       char *p;
+       
+       p = strrchr( path, '\\' );
+       if ( p )
+               p++;
+       else
+               p = path;
+               
+       return p;
+}
+
+/**********************************************************************
+ handle enumeration of values below 
+ KEY_PRINTING\Environments\<arch>\<version>\<drivername>
+ *********************************************************************/
+static int print_subpath_values_environments( char *key, REGVAL_CTR *val )
+{
+       char            *keystr;
+       char            *key2 = NULL;
+       char            *base, *new_path;
+       fstring         env;
+       fstring         driver;
+       int             version;
+       NT_PRINTER_DRIVER_INFO_LEVEL    driver_ctr;
+       NT_PRINTER_DRIVER_INFO_LEVEL_3  *info3;
+       WERROR          w_result;
+       char            *buffer = NULL;
+       char            *buffer2 = NULL;
+       int             buffer_size = 0;
+       int             i, length;
+       char            *filename;
+       
+       DEBUG(8,("print_subpath_values_environments: Enter key => [%s]\n", key ? key : "NULL"));
+       
        if ( !key )
+               return 0;
+               
+       /* 
+        * The only key below KEY_PRINTING\Environments that 
+        * posseses values is each specific printer driver 
+        * First get the arch, version, & driver name
+        */
+       
+       /* env */
+       
+       key2 = strdup( key );
+       keystr = key2;
+       reg_split_path( keystr, &base, &new_path );
+       if ( !base || !new_path )
+               return 0;
+       fstrcpy( env, base );
+       
+       /* version */
+       
+       keystr = new_path;
+       reg_split_path( keystr, &base, &new_path );
+       if ( !base || !new_path )
+               return 0;
+       version = atoi( base );
+
+       /* printer driver name */
+       
+       keystr = new_path;
+       reg_split_path( keystr, &base, &new_path );
+       /* new_path should be NULL here since this must be the last key */
+       if ( !base || new_path )
+               return 0;
+       fstrcpy( driver, base );
+
+       w_result = get_a_printer_driver( &driver_ctr, 3, driver, env, version );
+
+       if ( !W_ERROR_IS_OK(w_result) )
+               return -1;
+               
+       /* build the values out of the driver information */
+       info3 = driver_ctr.info_3;
+       
+       filename = dos_basename( info3->driverpath );
+       regval_ctr_addvalue( val, "Driver",             REG_SZ,       filename, strlen(filename)+1 );
+       filename = dos_basename( info3->configfile );
+       regval_ctr_addvalue( val, "Configuration File", REG_SZ,       filename, strlen(filename)+1 );
+       filename = dos_basename( info3->datafile );
+       regval_ctr_addvalue( val, "Data File",          REG_SZ,       filename, strlen(filename)+1 );
+       filename = dos_basename( info3->helpfile );
+       regval_ctr_addvalue( val, "Help File",          REG_SZ,       filename, strlen(filename)+1 );
+               
+       regval_ctr_addvalue( val, "Data Type",          REG_SZ,       info3->defaultdatatype, strlen(info3->defaultdatatype)+1 );
+       
+       regval_ctr_addvalue( val, "Version",            REG_DWORD,    (char*)&info3->cversion, sizeof(info3->cversion) );
+       
+       if ( info3->dependentfiles )
        {
-               /* listed architectures of installed drivers */
+               /* place the list of dependent files in a single 
+                  character buffer, separating each file name by
+                  a NULL */
+                  
+               for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ )
+               {
+                       /* strip the path to only the file's base name */
+               
+                       filename = dos_basename( info3->dependentfiles[i] );
+                       
+                       length = strlen(filename);
+               
+                       buffer2 = Realloc( buffer, buffer_size + length + 1 );
+                       if ( !buffer2 )
+                               break;
+                       buffer = buffer2;
+               
+                       memcpy( buffer+buffer_size, filename, length+1 );
                
+                       buffer_size += length + 1;
+               }
+               
+               /* terminated by double NULL.  Add the final one here */
+               
+               buffer2 = Realloc( buffer, buffer_size + 1 );
+               if ( !buffer2 ) {
+                       SAFE_FREE( buffer );
+                       buffer_size = 0;
+               }
+               else {
+                       buffer = buffer2;
+                       buffer[buffer_size++] = '\0';
+               }
        }
        
+       regval_ctr_addvalue( val, "Dependent Files",    REG_MULTI_SZ, buffer, buffer_size );
        
-       return 0;
+       free_a_printer_driver( driver_ctr, 3 );
+       SAFE_FREE( key2 );
+       SAFE_FREE( buffer );
+               
+       DEBUG(8,("print_subpath_values_environments: Exit\n"));
+       
+       return regval_ctr_numvals( val );
 }
 
+
 /**********************************************************************
  handle enumeration of subkeys below KEY_PRINTING\Forms
  Really just a stub function, but left here in case it needs to
@@ -263,6 +515,8 @@ static int handle_printing_subpath( char *key, REGSUBKEY_CTR *subkeys, REGVAL_CT
                case KEY_INDEX_ENVIR:
                        if ( subkeys )
                                print_subpath_environments( p, subkeys );
+                       if ( val )
+                               print_subpath_values_environments( p, val );
                        break;
                
                case KEY_INDEX_FORMS:
index 3987f208851984d2dc9778b5a7eb15b89903bf8e..83b55863eb1c134ce108748867fe796d9ce9f8f7 100644 (file)
@@ -6,6 +6,7 @@
  *  Copyright (C) Paul Ashton                       1997.
  *  Copyright (C) Marc Jacobsen                     1999.
  *  Copyright (C) Simo Sorce                        2000.
+ *  Copyright (C) Gerald Carter                     2002.
  *  
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_PARSE
 
+/*******************************************************************
+ Fill in a BUFFER2 for the data given a REGISTRY_VALUE
+ *******************************************************************/
+
+static uint32 reg_init_buffer2( BUFFER2 *buf2, REGISTRY_VALUE *val )
+{
+       UNISTR2         unistr;
+       uint32          real_size = 0;
+       char            *string;
+       char            *list = NULL;
+       char            *list2 = NULL;
+       
+       if ( !buf2 || !val )
+               return 0;
+               
+       real_size = val->size;
+               
+       switch (val->type )
+       {
+               case REG_SZ:
+                       string = (char*)val->data_p;
+                       DEBUG(10,("reg_init_buffer2: REG_SZ string => [%s]\n", string));
+                       
+                       init_unistr2( &unistr, (char*)val->data_p, strlen((char*)val->data_p)+1 );
+                       init_buffer2( buf2, (char*)unistr.buffer, unistr.uni_str_len*2 );
+                       real_size = unistr.uni_str_len*2;
+                       break;
+                       
+               case REG_MULTI_SZ:
+                       string = (char*)val->data_p;
+                       real_size = 0;
+                       while ( string && *string )
+                       {
+                               DEBUG(10,("reg_init_buffer2: REG_MULTI_SZ string => [%s], size => [%d]\n", string, real_size ));
+                               
+                               init_unistr2( &unistr, string, strlen(string)+1 );
+                               
+                               list2 = Realloc( list, real_size + unistr.uni_str_len*2 );
+                               if ( !list2 )
+                                       break;
+                               list = list2;
+                               
+                               memcpy( list+real_size, unistr.buffer, unistr.uni_str_len*2 );
+                               
+                               real_size += unistr.uni_str_len*2;
+                               
+                               string += strlen(string)+1;
+                       }
+                       
+                       list2 = Realloc( list, real_size + 2 );
+                       if ( !list2 )
+                               break;
+                       list = list2;
+                       list[real_size++] = 0x0;
+                       list[real_size++] = 0x0;
+                       
+                       init_buffer2( buf2, (char*)list, real_size );
+                       
+                       DEBUG(10,("reg_init_buffer2: REG_MULTI_SZ size => [%d]\n", real_size ));
+                       
+                       break;
+                       
+               case REG_BINARY:
+                       DEBUG(10,("reg_init_buffer2: REG_BINARY size => [%d]\n", val->size ));
+                       
+                       init_buffer2( buf2, val->data_p, val->size );
+                       break;
+                       
+               case REG_DWORD: 
+                       DEBUG(10,("reg_init_buffer2: REG_DWORD value => [%d]\n", *(uint32*)val->data_p));
+                       init_buffer2( buf2, val->data_p, val->size );
+                       break;
+                       
+               default:
+                       DEBUG(0,("reg_init_buffer2: Unsupported registry data type [%d]\n", val->type));
+                       break;
+       }
+       
+       SAFE_FREE( list );
+
+       return real_size;
+}
+
 /*******************************************************************
  Inits a structure.
 ********************************************************************/
@@ -165,6 +249,8 @@ BOOL reg_io_r_open_hklm(char *desc, REG_R_OPEN_HKLM * r_r, prs_struct *ps,
 }
 
 
+
+
 /*******************************************************************
  Inits a structure.
 ********************************************************************/
@@ -1023,6 +1109,45 @@ BOOL reg_io_q_info(char *desc,  REG_Q_INFO *r_q, prs_struct *ps, int depth)
        return True;
 }
 
+/*******************************************************************
+ Inits a structure.
+ New version to replace older init_reg_r_info()
+********************************************************************/
+
+BOOL new_init_reg_r_info(uint32 include_keyval, REG_R_INFO *r_r,
+                    REGISTRY_VALUE *val, NTSTATUS status)
+{
+       uint32          buf_len = 0;
+       
+       if(r_r == NULL)
+               return False;
+       
+       if ( !val )
+               return False;
+  
+       r_r->ptr_type = 1;
+       r_r->type = val->type;
+
+       /* if include_keyval is not set, don't send the key value, just
+          the buflen data. probably used by NT5 to allocate buffer space - SK */
+
+       if ( include_keyval ) {
+               r_r->ptr_uni_val = 1;
+               buf_len = reg_init_buffer2( &r_r->uni_val, val );
+       
+       }
+
+       r_r->ptr_max_len = 1;
+       r_r->buf_max_len = buf_len;
+
+       r_r->ptr_len = 1;
+       r_r->buf_len = buf_len;
+
+       r_r->status = status;
+
+       return True;
+}
+
 /*******************************************************************
  Inits a structure.
 ********************************************************************/
@@ -1030,28 +1155,27 @@ BOOL reg_io_q_info(char *desc,  REG_Q_INFO *r_q, prs_struct *ps, int depth)
 BOOL init_reg_r_info(uint32 include_keyval, REG_R_INFO *r_r,
                     BUFFER2* buf, uint32 type, NTSTATUS status)
 {
-  if(r_r == NULL)
-    return False;
-
+       if(r_r == NULL)
+               return False;
   
-  r_r->ptr_type = 1;
-  r_r->type = type;
+       r_r->ptr_type = 1;
+       r_r->type = type;
 
-  /* if include_keyval is not set, don't send the key value, just
-     the buflen data. probably used by NT5 to allocate buffer space - SK */
-  r_r->ptr_uni_val = include_keyval ? 1:0;
-  r_r->uni_val = buf;
+       /* if include_keyval is not set, don't send the key value, just
+          the buflen data. probably used by NT5 to allocate buffer space - SK */
 
-  r_r->ptr_max_len = 1;
-  r_r->buf_max_len = r_r->uni_val->buf_max_len;
+       r_r->ptr_uni_val = include_keyval ? 1:0;
+       r_r->uni_val = *buf;
 
-  r_r->ptr_len = 1;
-  r_r->buf_len = r_r->uni_val->buf_len;
+       r_r->ptr_max_len = 1;
+       r_r->buf_max_len = r_r->uni_val.buf_max_len;
 
-  r_r->status = status;
+       r_r->ptr_len = 1;
+       r_r->buf_len = r_r->uni_val.buf_len;
 
-  return True;
-  
+       r_r->status = status;
+
+       return True;
 }
 
 /*******************************************************************
@@ -1081,7 +1205,7 @@ BOOL reg_io_r_info(char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth)
                return False;
 
        if(r_r->ptr_uni_val != 0) {
-               if(!smb_io_buffer2("uni_val", r_r->uni_val, r_r->ptr_uni_val, ps, depth))
+               if(!smb_io_buffer2("uni_val", &r_r->uni_val, r_r->ptr_uni_val, ps, depth))
                        return False;
        }
 
@@ -1144,10 +1268,16 @@ makes a structure.
 
 void init_reg_r_enum_val(REG_R_ENUM_VALUE *r_u, REGISTRY_VALUE *val )
 {
+       uint32 real_size;
+       
+       DEBUG(8,("init_reg_r_enum_val: Enter\n"));
+       
        ZERO_STRUCTP(r_u);
 
        /* value name */
 
+       DEBUG(10,("init_reg_r_enum_val: Valuename => [%s]\n", val->valuename));
+       
        init_uni_hdr( &r_u->hdr_name, strlen(val->valuename)+1 );
        init_unistr2( &r_u->uni_name, val->valuename, strlen(val->valuename)+1 );
                
@@ -1156,18 +1286,20 @@ void init_reg_r_enum_val(REG_R_ENUM_VALUE *r_u, REGISTRY_VALUE *val )
        r_u->ptr_type = 1;
        r_u->type = val->type;
 
-       /* data */
+       /* REG_SZ & REG_MULTI_SZ must be converted to UNICODE */
        
        r_u->ptr_value = 1;
-       init_buffer2( &r_u->buf_value, val->data.void_ptr, val->size );
+       real_size = reg_init_buffer2( &r_u->buf_value, val );
        
        /* lengths */
 
        r_u->ptr1 = 1;
-       r_u->len_value1 = val->size;
+       r_u->len_value1 = real_size;
        
        r_u->ptr2 = 1;
-       r_u->len_value2 = val->size;
+       r_u->len_value2 = real_size;
+               
+       DEBUG(8,("init_reg_r_enum_val: Exit\n"));
 }
 
 /*******************************************************************
index ee873e32e9f530492128ea09f426563ae13388dc..cb96005db10df7f8aab376b8f8b3a262d388a117 100644 (file)
@@ -83,7 +83,7 @@ static BOOL api_reg_open_hklm(pipes_struct *p)
 }
 
 /*******************************************************************
- api_reg_open_khlm
+ api_reg_open_khu
  ********************************************************************/
 
 static BOOL api_reg_open_hku(pipes_struct *p)
@@ -108,6 +108,32 @@ static BOOL api_reg_open_hku(pipes_struct *p)
        return True;
 }
 
+/*******************************************************************
+ api_reg_open_khcr
+ ********************************************************************/
+
+static BOOL api_reg_open_hkcr(pipes_struct *p)
+{
+       REG_Q_OPEN_HKCR q_u;
+       REG_R_OPEN_HKCR r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       /* grab the reg open */
+       if(!reg_io_q_open_hkcr("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _reg_open_hkcr(p, &q_u, &r_u);
+
+       if(!reg_io_r_open_hkcr("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
 
 /*******************************************************************
  api_reg_open_entry
@@ -324,6 +350,7 @@ static struct api_struct api_reg_cmds[] =
 {
        { "REG_CLOSE"              , REG_CLOSE              , api_reg_close            },
        { "REG_OPEN_ENTRY"         , REG_OPEN_ENTRY         , api_reg_open_entry       },
+       { "REG_OPEN_HKCR"          , REG_OPEN_HKCR          , api_reg_open_hkcr        },
        { "REG_OPEN_HKLM"          , REG_OPEN_HKLM          , api_reg_open_hklm        },
        { "REG_OPEN_HKU"           , REG_OPEN_HKU           , api_reg_open_hku         },
        { "REG_ENUM_KEY"           , REG_ENUM_KEY           , api_reg_enum_key         },
index 99439bcc3881f5d73b07f3edc89eb59e6d6ad6ed..3afb2a2c81291b5a2f8098df4b8fec980147bb2d 100644 (file)
@@ -78,33 +78,35 @@ static NTSTATUS open_registry_key(pipes_struct *p, POLICY_HND *hnd, REGISTRY_KEY
                                char *subkeyname, uint32 access_granted  )
 {
        REGISTRY_KEY    *regkey = NULL;
-       pstring         parent_keyname;
        NTSTATUS        result = NT_STATUS_OK;
        REGSUBKEY_CTR   subkeys;
        
-       if ( parent ) {
-               pstrcpy( parent_keyname, parent->name );
-               pstrcat( parent_keyname, "\\" );
-       }
-       else
-               *parent_keyname = '\0';
-
-       DEBUG(7,("open_registry_key: name = [%s][%s]\n", parent_keyname, subkeyname));
+       DEBUG(7,("open_registry_key: name = [%s][%s]\n", 
+               parent ? parent->name : "NULL", subkeyname));
 
-       /* All registry keys **must** have a name of non-zero length */
-       
-       if (!subkeyname || !*subkeyname )
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-                       
        if ((regkey=(REGISTRY_KEY*)malloc(sizeof(REGISTRY_KEY))) == NULL)
                return NT_STATUS_NO_MEMORY;
                
        ZERO_STRUCTP( regkey );
        
-       /* copy the name */
+       /* 
+        * very crazy, but regedit.exe on Win2k will attempt to call 
+        * REG_OPEN_ENTRY with a keyname of "".  We should return a new 
+        * (second) handle here on the key->name.  regedt32.exe does 
+        * not do this stupidity.   --jerry
+        */
        
-       pstrcpy( regkey->name, parent_keyname );
-       pstrcat( regkey->name, subkeyname );
+       if (!subkeyname || !*subkeyname ) {
+               pstrcpy( regkey->name, parent->name );  
+       }
+       else {
+               pstrcpy( regkey->name, "" );
+               if ( parent ) {
+                       pstrcat( regkey->name, parent->name );
+                       pstrcat( regkey->name, "\\" );
+               }
+               pstrcat( regkey->name, subkeyname );
+       }
        
        /* Look up the table of registry I/O operations */
 
@@ -227,7 +229,8 @@ static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
        if ( !key )
                return False;
 
-       ZERO_STRUCTP( &val );
+
+       ZERO_STRUCTP( &values );
        
        regval_ctr_init( &values );
        
@@ -274,7 +277,6 @@ NTSTATUS _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
 }
 
 /*******************************************************************
- reg_reply_open
  ********************************************************************/
 
 NTSTATUS _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_u)
@@ -283,7 +285,14 @@ NTSTATUS _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *
 }
 
 /*******************************************************************
- reg_reply_open
+ ********************************************************************/
+
+NTSTATUS _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HKCR *q_u, REG_R_OPEN_HKCR *r_u)
+{
+       return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, 0x0 );
+}
+
+/*******************************************************************
  ********************************************************************/
 
 NTSTATUS _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HKU *q_u, REG_R_OPEN_HKU *r_u)
@@ -310,7 +319,7 @@ NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTR
        rpcstr_pull(name,q_u->uni_name.buffer,sizeof(name),q_u->uni_name.uni_str_len*2,0);
        
        DEBUG(5,("reg_open_entry: Enter\n"));
-       
+                  
        result = open_registry_key( p, &pol, key, name, 0x0 );
        
        init_reg_r_open_entry( r_u, &pol, result );
@@ -326,64 +335,83 @@ NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTR
 
 NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
 {
-       NTSTATUS status = NT_STATUS_OK;
-       char *value = NULL;
-       uint32 type = 0x1; /* key type: REG_SZ */
-       UNISTR2 *uni_key = NULL;
-       BUFFER2 *buf = NULL;
-       fstring name;
-       REGISTRY_KEY *key = find_regkey_index_by_hnd( p, &q_u->pol );
+       NTSTATUS                status = NT_STATUS_NO_SUCH_FILE;
+       fstring                 name;
+       REGISTRY_KEY            *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
+       REGISTRY_VALUE          *val = NULL;
+       REGISTRY_VALUE          emptyval;
+       REGVAL_CTR              regvals;
+       int                     i;
 
        DEBUG(5,("_reg_info: Enter\n"));
 
-       if ( !key )
+       if ( !regkey )
                return NT_STATUS_INVALID_HANDLE;
                
-       DEBUG(7,("_reg_info: policy key name = [%s]\n", key->name));
-
+       DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
+       
        rpcstr_pull(name, q_u->uni_type.buffer, sizeof(name), q_u->uni_type.uni_str_len*2, 0);
 
-       DEBUG(5,("reg_info: checking subkey: %s\n", name));
-
-       uni_key = (UNISTR2 *)talloc_zero(p->mem_ctx, sizeof(UNISTR2));
-       buf = (BUFFER2 *)talloc_zero(p->mem_ctx, sizeof(BUFFER2));
+       DEBUG(5,("reg_info: looking up value: [%s]\n", name));
 
-       if (!uni_key || !buf)
-               return NT_STATUS_NO_MEMORY;
+       ZERO_STRUCTP( &regvals );
+       
+       regval_ctr_init( &regvals );
 
+       /* couple of hard coded registry values */
+       
        if ( strequal(name, "RefusePasswordChange") ) {
-               type=0xF770;
-               status = NT_STATUS_NO_SUCH_FILE;
-               init_unistr2(uni_key, "", 0);
-               init_buffer2(buf, (uint8*) uni_key->buffer, uni_key->uni_str_len*2);
-               
-               buf->buf_max_len=4;
+               ZERO_STRUCTP( &emptyval );
+               val = &emptyval;
+       
+               goto out;
+       }
 
+       if ( strequal(name, "ProductType") ) {
+               /* This makes the server look like a member server to clients */
+               /* which tells clients that we have our own local user and    */
+               /* group databases and helps with ACL support.                */
+               
+               switch (lp_server_role()) {
+                       case ROLE_DOMAIN_PDC:
+                       case ROLE_DOMAIN_BDC:
+                               regval_ctr_addvalue( &regvals, "ProductType", REG_SZ, "LanmanNT", strlen("LanmanNT")+1 );
+                               break;
+                       case ROLE_STANDALONE:
+                               regval_ctr_addvalue( &regvals, "ProductType", REG_SZ, "ServerNT", strlen("ServerNT")+1 );
+                               break;
+                       case ROLE_DOMAIN_MEMBER:
+                               regval_ctr_addvalue( &regvals, "ProductType", REG_SZ, "WinNT", strlen("WinNT")+1 );
+                               break;
+               }
+               
+               val = regval_ctr_specific_value( &regvals, 0 );
+               
+               status = NT_STATUS_OK;
+               
                goto out;
        }
 
-       switch (lp_server_role()) {
-               case ROLE_DOMAIN_PDC:
-               case ROLE_DOMAIN_BDC:
-                       value = "LanmanNT";
-                       break;
-               case ROLE_STANDALONE:
-                       value = "ServerNT";
-                       break;
-               case ROLE_DOMAIN_MEMBER:
-                       value = "WinNT";
+       /* else fall back to actually looking up the value */
+       
+       for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ ) 
+       {
+               DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
+               if ( StrCaseCmp( val->valuename, name ) == 0 ) {
+                       DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
+                       status = NT_STATUS_OK;
                        break;
+               }
+               
+               free_registry_value( val );
        }
 
-       /* This makes the server look like a member server to clients */
-       /* which tells clients that we have our own local user and    */
-       /* group databases and helps with ACL support.                */
-
-       init_unistr2(uni_key, value, strlen(value)+1);
-       init_buffer2(buf, (uint8*)uni_key->buffer, uni_key->uni_str_len*2);
   
- out:
-       init_reg_r_info(q_u->ptr_buf, r_u, buf, type, status);
+out:
+       new_init_reg_r_info(q_u->ptr_buf, r_u, val, status);
+       
+       regval_ctr_destroy( &regvals );
+       free_registry_value( val );
 
        DEBUG(5,("_reg_info: Exit\n"));
 
@@ -455,7 +483,7 @@ NTSTATUS _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u
 {
        NTSTATUS        status = NT_STATUS_OK;
        REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
-       char            *subkey;
+       char            *subkey = NULL;
        
        
        DEBUG(5,("_reg_enum_key: Enter\n"));
@@ -518,7 +546,7 @@ NTSTATUS _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALU
        DEBUG(5,("_reg_enum_value: Exit\n"));
        
 done:  
-       SAFE_FREE( val );
+       free_registry_value( val );
        
        return status;
 }