diff options
author | Gerald Carter <jerry@samba.org> | 2002-07-24 06:42:09 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2002-07-24 06:42:09 +0000 |
commit | c808cc3643f06c72f870d0b14a37c7a46627e2fa (patch) | |
tree | ba307c845f17a592388770b115322855d56fe888 | |
parent | 84f2875d7bac30e75397bbf89d3d5e79ba790ddc (diff) | |
download | samba-c808cc3643f06c72f870d0b14a37c7a46627e2fa.tar.gz samba-c808cc3643f06c72f870d0b14a37c7a46627e2fa.tar.bz2 samba-c808cc3643f06c72f870d0b14a37c7a46627e2fa.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....
(This used to be commit 419d7208e8384e4ad2c4dd328ad5e630971bc76c)
-rw-r--r-- | source3/include/rpc_reg.h | 13 | ||||
-rw-r--r-- | source3/registry/reg_db.c | 9 | ||||
-rw-r--r-- | source3/registry/reg_frontend.c | 138 | ||||
-rw-r--r-- | source3/registry/reg_printing.c | 258 | ||||
-rw-r--r-- | source3/rpc_parse/parse_reg.c | 174 | ||||
-rw-r--r-- | source3/rpc_server/srv_reg.c | 29 | ||||
-rw-r--r-- | source3/rpc_server/srv_reg_nt.c | 154 |
7 files changed, 627 insertions, 148 deletions
diff --git a/source3/include/rpc_reg.h b/source3/include/rpc_reg.h index d025cb2c0d..e2347c328b 100644 --- a/source3/include/rpc_reg.h +++ b/source3/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/source3/registry/reg_db.c b/source3/registry/reg_db.c index 714e14e48b..773a4f7fb5 100644 --- a/source3/registry/reg_db.c +++ b/source3/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/source3/registry/reg_frontend.c b/source3/registry/reg_frontend.c index a282207376..db612709d1 100644 --- a/source3/registry/reg_frontend.c +++ b/source3/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/source3/registry/reg_printing.c b/source3/registry/reg_printing.c index f4c1feb281..d8e0f18953 100644 --- a/source3/registry/reg_printing.c +++ b/source3/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/source3/rpc_parse/parse_reg.c b/source3/rpc_parse/parse_reg.c index 3987f20885..83b55863eb 100644 --- a/source3/rpc_parse/parse_reg.c +++ b/source3/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/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c index ee873e32e9..cb96005db1 100644 --- a/source3/rpc_server/srv_reg.c +++ b/source3/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/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c index 99439bcc38..3afb2a2c81 100644 --- a/source3/rpc_server/srv_reg_nt.c +++ b/source3/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( ®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; + } + 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; } - 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( ®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; } |