summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2002-07-24 06:42:09 +0000
committerGerald Carter <jerry@samba.org>2002-07-24 06:42:09 +0000
commit419d7208e8384e4ad2c4dd328ad5e630971bc76c (patch)
treecc294fafea3cb5d3a357976503fa378c3ee8e1bb
parent2febc7ce1aa6b01ec68bd007ce0286813dff301d (diff)
downloadsamba-419d7208e8384e4ad2c4dd328ad5e630971bc76c.tar.gz
samba-419d7208e8384e4ad2c4dd328ad5e630971bc76c.tar.xz
samba-419d7208e8384e4ad2c4dd328ad5e630971bc76c.zip
several changes in this checkin
* 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....
-rw-r--r--source/include/rpc_reg.h13
-rw-r--r--source/registry/reg_db.c9
-rw-r--r--source/registry/reg_frontend.c138
-rw-r--r--source/registry/reg_printing.c258
-rw-r--r--source/rpc_parse/parse_reg.c174
-rw-r--r--source/rpc_server/srv_reg.c29
-rw-r--r--source/rpc_server/srv_reg_nt.c154
7 files changed, 627 insertions, 148 deletions
diff --git a/source/include/rpc_reg.h b/source/include/rpc_reg.h
index d025cb2c0d8..e2347c328be 100644
--- a/source/include/rpc_reg.h
+++ b/source/include/rpc_reg.h
@@ -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;
diff --git a/source/registry/reg_db.c b/source/registry/reg_db.c
index 714e14e48ba..773a4f7fb5b 100644
--- a/source/registry/reg_db.c
+++ b/source/registry/reg_db.c
@@ -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;
}
diff --git a/source/registry/reg_frontend.c b/source/registry/reg_frontend.c
index a2822073765..db612709d10 100644
--- a/source/registry/reg_frontend.c
+++ b/source/registry/reg_frontend.c
@@ -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;
}
diff --git a/source/registry/reg_printing.c b/source/registry/reg_printing.c
index f4c1feb281f..d8e0f18953c 100644
--- a/source/registry/reg_printing.c
+++ b/source/registry/reg_printing.c
@@ -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:
diff --git a/source/rpc_parse/parse_reg.c b/source/rpc_parse/parse_reg.c
index 3987f208851..83b55863eb1 100644
--- a/source/rpc_parse/parse_reg.c
+++ b/source/rpc_parse/parse_reg.c
@@ -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
@@ -28,6 +29,89 @@
#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.
********************************************************************/
@@ -1025,33 +1111,71 @@ BOOL reg_io_q_info(char *desc, REG_Q_INFO *r_q, prs_struct *ps, int depth)
/*******************************************************************
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.
********************************************************************/
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"));
}
/*******************************************************************
diff --git a/source/rpc_server/srv_reg.c b/source/rpc_server/srv_reg.c
index ee873e32e9f..cb96005db10 100644
--- a/source/rpc_server/srv_reg.c
+++ b/source/rpc_server/srv_reg.c
@@ -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 },
diff --git a/source/rpc_server/srv_reg_nt.c b/source/rpc_server/srv_reg_nt.c
index 99439bcc388..3afb2a2c812 100644
--- a/source/rpc_server/srv_reg_nt.c
+++ b/source/rpc_server/srv_reg_nt.c
@@ -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;
}