mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
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....
(This used to be commit 419d7208e8
)
This commit is contained in:
parent
84f2875d7b
commit
c808cc3643
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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" ));
|
||||
|
||||
if ( !key )
|
||||
/* listed architectures of installed drivers */
|
||||
|
||||
if ( !key )
|
||||
{
|
||||
/* listed architectures of installed drivers */
|
||||
/* 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 */
|
||||
|
||||
return 0;
|
||||
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 )
|
||||
{
|
||||
/* 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 );
|
||||
|
||||
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:
|
||||
|
@ -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
|
||||
@ -27,6 +28,89 @@
|
||||
#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"));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -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 },
|
||||
|
@ -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 ? parent->name : "NULL", subkeyname));
|
||||
|
||||
DEBUG(7,("open_registry_key: name = [%s][%s]\n", parent_keyname, 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));
|
||||
DEBUG(5,("reg_info: looking up value: [%s]\n", name));
|
||||
|
||||
uni_key = (UNISTR2 *)talloc_zero(p->mem_ctx, sizeof(UNISTR2));
|
||||
buf = (BUFFER2 *)talloc_zero(p->mem_ctx, sizeof(BUFFER2));
|
||||
|
||||
if (!uni_key || !buf)
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
ZERO_STRUCTP( ®vals );
|
||||
|
||||
regval_ctr_init( ®vals );
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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";
|
||||
break;
|
||||
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( ®vals, "ProductType", REG_SZ, "LanmanNT", strlen("LanmanNT")+1 );
|
||||
break;
|
||||
case ROLE_STANDALONE:
|
||||
regval_ctr_addvalue( ®vals, "ProductType", REG_SZ, "ServerNT", strlen("ServerNT")+1 );
|
||||
break;
|
||||
case ROLE_DOMAIN_MEMBER:
|
||||
regval_ctr_addvalue( ®vals, "ProductType", REG_SZ, "WinNT", strlen("WinNT")+1 );
|
||||
break;
|
||||
}
|
||||
|
||||
val = regval_ctr_specific_value( ®vals, 0 );
|
||||
|
||||
status = NT_STATUS_OK;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
/* 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 );
|
||||
}
|
||||
|
||||
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( ®vals );
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user