From a43d9788fa8823d678ee72470421b980165ec2b0 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 18 Jul 2002 23:00:24 +0000 Subject: [PATCH] virtual registry framework with initial printing hooks. --- source/Makefile.in | 5 +- source/include/adt_tree.h | 38 +++ source/include/includes.h | 1 + source/include/rpc_reg.h | 43 ++- source/lib/adt_tree.c | 414 +++++++++++++++++++++++ source/registry/reg_cachehook.c | 96 ++++++ source/registry/{reg_frontend.c => reg_db.c} | 97 +++--- source/registry/reg_frontend.c | 473 ++++++++------------------- source/registry/reg_printing.c | 243 ++++++++++++++ source/rpc_server/srv_reg_nt.c | 198 ++++++----- source/script/mkproto.awk | 2 +- 11 files changed, 1135 insertions(+), 475 deletions(-) create mode 100644 source/include/adt_tree.h create mode 100644 source/lib/adt_tree.c create mode 100644 source/registry/reg_cachehook.c copy source/registry/{reg_frontend.c => reg_db.c} (83%) rewrite source/registry/reg_frontend.c (75%) create mode 100644 source/registry/reg_printing.c diff --git a/source/Makefile.in b/source/Makefile.in index b4f9c8c5e2e..765b22a7736 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -138,7 +138,7 @@ LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \ lib/md5.o lib/hmacmd5.o lib/iconv.o lib/smbpasswd.o \ nsswitch/wb_client.o nsswitch/wb_common.o \ lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ - $(TDB_OBJ) + lib/adt_tree.o $(TDB_OBJ) READLINE_OBJ = lib/readline.o @@ -177,7 +177,8 @@ LIBMSRPC_SERVER_OBJ = libsmb/trust_passwd.o LIBMSRPC_PICOBJ = $(LIBMSRPC_OBJ:.o=.po) -REGISTRY_OBJ = registry/reg_frontend.o +REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \ + registry/reg_db.o RPC_SERVER_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o \ rpc_server/srv_lsa_hnd.o rpc_server/srv_netlog.o rpc_server/srv_netlog_nt.o \ diff --git a/source/include/adt_tree.h b/source/include/adt_tree.h new file mode 100644 index 00000000000..b1bf7ad85dc --- /dev/null +++ b/source/include/adt_tree.h @@ -0,0 +1,38 @@ +/* + * Unix SMB/CIFS implementation. + * Generic Abstract Data Types + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef ADT_TREE_H +#define ADT_TREE_H + +typedef struct _tree_node { + struct _tree_node *parent; + struct _tree_node **children; + int num_children; + char *key; + void *data_p; +} TREE_NODE; + +typedef struct _tree_root { + TREE_NODE *root; + int (*compare)(void* x, void *y); + void (*free)(void *p); +} SORTED_TREE; + +#endif diff --git a/source/include/includes.h b/source/include/includes.h index 435810a1bab..04d11afafb9 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -710,6 +710,7 @@ extern int errno; #include "messages.h" #include "charset.h" #include "dynconfig.h" +#include "adt_tree.h" #include "util_getent.h" diff --git a/source/include/rpc_reg.h b/source/include/rpc_reg.h index 8ebfc888ed8..9c5f614f91f 100644 --- a/source/include/rpc_reg.h +++ b/source/include/rpc_reg.h @@ -65,6 +65,7 @@ #define KEY_HKLM "HKLM" #define KEY_HKU "HKU" +#define KEY_PRINTING "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print" /* Registry data types */ @@ -86,16 +87,52 @@ #define REG_FORCE_SHUTDOWN 0x001 #define REG_REBOOT_ON_SHUTDOWN 0x100 +/* structure to contain registry values */ + +typedef struct _RegistryValue { + fstring valuename; + uint16 type; + uint32 size; /* in bytes */ + union { + char *string; + uint32 dword; + uint8 *binary; + } data; +} REGISTRY_VALUE; + + +/* + * container for function pointers to enumeration routines + * for vitural registry view + */ + +typedef struct _reg_ops { + /* functions for enumerating subkeys and values */ + int (*subkey_fn)( char *key, char **subkeys ); + int (*subkey_specific_fn)( char *key, char** subkey, uint32 index ); + int (*value_fn) ( char *key, REGISTRY_VALUE **val ); + BOOL (*store_subkeys_fn)( char *key, char **subkeys, uint32 num_subkeys ); + BOOL (*store_values_fn)( char *key, REGISTRY_VALUE **val, uint32 num_values ); +} REGISTRY_OPS; + +typedef struct _reg_hook { + char *keyname; /* full path to name of key */ + REGISTRY_OPS *ops; /* registry function hooks */ +} REGISTRY_HOOK; + + + /* structure to store the registry handles */ typedef struct _RegistryKey { struct _RegistryKey *prev, *next; - fstring name; /* name of registry key */ POLICY_HND hnd; + fstring name; /* full name of registry key */ + REGISTRY_HOOK *hook; -} Registry_Key; +} REGISTRY_KEY; /* REG_Q_OPEN_HKCR */ @@ -123,7 +160,7 @@ typedef struct q_reg_open_hklm_info uint32 ptr; uint16 unknown_0; /* 0xE084 - 16 bit unknown */ uint16 unknown_1; /* random. changes */ - uint32 access_mask; /* 0x0000 0002 - 32 bit unknown */ + uint32 access_mask; } REG_Q_OPEN_HKLM; diff --git a/source/lib/adt_tree.c b/source/lib/adt_tree.c new file mode 100644 index 00000000000..e3519c6c41d --- /dev/null +++ b/source/lib/adt_tree.c @@ -0,0 +1,414 @@ +/* + * Unix SMB/CIFS implementation. + * Generic Abstract Data Types + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + + +/************************************************************************** + Initialize the tree's root. The cmp_fn is a callback function used + for comparision of two children + *************************************************************************/ + +SORTED_TREE* sorted_tree_init( int (cmp_fn)(void*, void*), + void (free_fn)(void*) ) +{ + SORTED_TREE *tree = NULL; + + if ( !(tree = (SORTED_TREE*)malloc( sizeof(SORTED_TREE) )) ) + return NULL; + + ZERO_STRUCTP( tree ); + + tree->compare = cmp_fn; + tree->free = free_fn; + + if ( !(tree->root = (TREE_NODE*)malloc( sizeof(TREE_NODE) )) ) { + SAFE_FREE( tree ); + return NULL; + } + + ZERO_STRUCTP( tree->root ); + + return tree; +} + + +/************************************************************************** + Delete a tree and free all allocated memory + *************************************************************************/ + +static void sorted_tree_destroy_children( TREE_NODE *root ) +{ + int i; + + if ( !root ) + return; + + for ( i=0; inum_children; i++ ) + { + sorted_tree_destroy_children( root->children[i] ); + } + + SAFE_FREE( root->children ); + SAFE_FREE( root->key ); + + return; +} + +/************************************************************************** + Delete a tree and free all allocated memory + *************************************************************************/ + +void sorted_tree_destroy( SORTED_TREE *tree ) +{ + if ( tree->root ) + sorted_tree_destroy_children( tree->root ); + + if ( tree->free ) + tree->free( tree->root ); + + SAFE_FREE( tree ); +} + +/************************************************************************** + Find the next child given a key string + *************************************************************************/ + +static TREE_NODE* sorted_tree_birth_child( TREE_NODE *node, char* key ) +{ + TREE_NODE *infant = NULL; + TREE_NODE *child, *crib; + TREE_NODE **siblings; + int i, result; + + if ( !(infant = (TREE_NODE*)malloc( sizeof(TREE_NODE) )) ) + return NULL; + + ZERO_STRUCTP( infant ); + + infant->key = strdup( key ); + infant->parent = node; + + siblings = Realloc( node->children, sizeof(TREE_NODE*)*(node->num_children+1) ); + + if ( siblings ) + node->children = siblings; + + node->num_children++; + + /* first child */ + + if ( node->num_children == 1 ) { + DEBUG(11,("sorted_tree_birth_child: First child of node [%s]! [%s]\n", + node->key ? node->key : "NULL", infant->key )); + node->children[0] = infant; + } + else + { + /* + * multiple siblings .... (at least 2 children) + * + * work from the end of the list forward + * The last child is not set at this point + * Insert the new infanct in ascending order + * from left to right + */ + + for ( i = node->num_children-1; i>=1; i-- ) + { + crib = node->children[i]; + child = node->children[i-1]; + + DEBUG(10,("sorted_tree_birth_child: Looking for crib; infant -> [%s], child -> [%s]\n", + infant->key, child->key)); + + /* the strings should never match assuming that we + have called sorted_tree_find_child() first */ + + result = StrCaseCmp( infant->key, child->key ); + if ( result > 0 ) { + crib = infant; + break; + } + + crib = child; + } + } + + return infant; +} +/************************************************************************** + Find the next child given a key string + *************************************************************************/ + +static TREE_NODE* sorted_tree_find_child( TREE_NODE *node, char* key ) +{ + TREE_NODE *next = NULL; + int i, result; + + if ( !node ) { + DEBUG(0,("sorted_tree_find_child: NULL node passed into function!\n")); + return NULL; + } + + if ( !key ) { + DEBUG(0,("sorted_tree_find_child: NULL key string passed into function!\n")); + return NULL; + } + + for ( i=0; i<(node->num_children); i++ ) + { + result = StrCaseCmp( key, node->children[i]->key ); + + if ( result == 0 ) + next = node->children[i]; + + /* if result > 0 then we've gone to far because + the list of children is sorted by key name + If result == 0, then we have a match */ + + if ( !(result < 0) ) + break; + } + + DEBUG(11,("sorted_tree_find_child: Did %s find [%s]\n", + next ? "" : "not", key )); + + return next; +} + +/************************************************************************** + Add a new node into the tree given a key path and a blob of data + *************************************************************************/ + +BOOL sorted_tree_add( SORTED_TREE *tree, const char *path, void *data_p ) +{ + char *str, *base, *path2; + TREE_NODE *current, *next; + BOOL ret = True; + + DEBUG(8,("sorted_tree_add: Enter\n")); + + if ( !path || *path != '/' ) { + DEBUG(0,("sorted_tree_add: Attempt to add a node with a bad path [%s]\n", + path ? path : "NULL" )); + return False; + } + + if ( !tree ) { + DEBUG(0,("sorted_tree_add: Attempt to add a node to an uninitialized tree!\n")); + return False; + } + + /* move past the first '/' */ + + path++; + path2 = strdup( path ); + if ( !path2 ) { + DEBUG(0,("sorted_tree_add: strdup() failed on string [%s]!?!?!\n", path)); + return False; + } + + + /* + * this works sort of like a 'mkdir -p' call, possibly + * creating an entire path to the new node at once + * The path should be of the form ///... + */ + + base = path2; + str = path2; + current = tree->root; + + do { + /* break off the remaining part of the path */ + + str = strchr( str, '/' ); + if ( str ) + *str = '\0'; + + /* iterate to the next child--birth it if necessary */ + + next = sorted_tree_find_child( current, base ); + if ( !next ) { + next = sorted_tree_birth_child( current, base ); + if ( !next ) { + DEBUG(0,("sorted_tree_add: Failed to create new child!\n")); + ret = False; + goto done; + } + } + current = next; + + /* setup the next part of the path */ + + base = str; + if ( base ) { + *base = '/'; + base++; + str = base; + } + + } while ( base != NULL ); + + current->data_p = data_p; + + DEBUG(10,("sorted_tree_add: Successfully added node [%s] to tree\n", + path )); + + DEBUG(8,("sorted_tree_add: Exit\n")); + +done: + SAFE_FREE( path2 ); + return ret; +} + + +/************************************************************************** + Recursive routine to print out all children of a TREE_NODE + *************************************************************************/ + +static void sorted_tree_print_children( TREE_NODE *node, int debug, char *path ) +{ + int i; + int num_children; + pstring path2; + + if ( !node ) + return; + + + if ( node->key ) + DEBUG(debug,("%s: [%s] (%s)\n", path ? path : "NULL", node->key, + node->data_p ? "data" : "NULL" )); + + *path2 = '\0'; + if ( path ) + pstrcpy( path2, path ); + pstrcat( path2, node->key ? node->key : "NULL" ); + pstrcat( path2, "/" ); + + num_children = node->num_children; + for ( i=0; ichildren[i], debug, path2 ); + + +} + +/************************************************************************** + Dump the kys for a tree to the log file + *************************************************************************/ + +void sorted_tree_print_keys( SORTED_TREE *tree, int debug ) +{ + int i; + int num_children = tree->root->num_children; + + if ( tree->root->key ) + DEBUG(debug,("ROOT/: [%s] (%s)\n", tree->root->key, + tree->root->data_p ? "data" : "NULL" )); + + for ( i=0; iroot->children[i], debug, + tree->root->key ? tree->root->key : "ROOT/" ); + } + +} + +/************************************************************************** + return the data_p for for the node in tree matching the key string + The key string is the full path. We must break it apart and walk + the tree + *************************************************************************/ + +void* sorted_tree_find( SORTED_TREE *tree, char *key ) +{ + char *keystr, *base, *str; + TREE_NODE *current; + void *result = NULL; + + DEBUG(10,("sorted_tree_find: Enter [%s]\n", key ? key : "NULL" )); + + /* sanity checks first */ + + if ( !key ) { + DEBUG(0,("sorted_tree_find: Attempt to search tree using NULL search string!\n")); + return NULL; + } + + if ( !tree ) { + DEBUG(0,("sorted_tree_find: Attempt to search an uninitialized tree using string [%s]!\n", + key ? key : "NULL" )); + return NULL; + } + + if ( !tree->root ) + return NULL; + + /* make a copy to play with */ + + keystr = strdup( key ); + if ( !keystr ) { + DEBUG(0,("sorted_tree_find: strdup() failed on string [%s]!?!?!\n", key)); + return NULL; + } + + /* start breaking the path apart */ + + base = keystr; + str = keystr; + current = tree->root; + + do + { + /* break off the remaining part of the path */ + + str = strchr( str, '/' ); + if ( str ) + *str = '\0'; + + DEBUG(10,("sorted_tree_find: [loop] key => [%s]\n", base)); + + /* iterate to the next child */ + + current = sorted_tree_find_child( current, base ); + + /* setup the next part of the path */ + + base = str; + if ( base ) { + *base = '/'; + base++; + str = base; + } + + } while ( base && current ); + + if ( current ) + result = current->data_p; + + SAFE_FREE( keystr ); + + DEBUG(10,("sorted_tree_find: Exit\n")); + + return result; +} + + diff --git a/source/registry/reg_cachehook.c b/source/registry/reg_cachehook.c new file mode 100644 index 00000000000..daf2f241800 --- /dev/null +++ b/source/registry/reg_cachehook.c @@ -0,0 +1,96 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Implementation of registry hook cache tree */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +static SORTED_TREE *cache_tree; + +/********************************************************************** + Initialize the cache tree + *********************************************************************/ + +BOOL reghook_cache_init( void ) +{ + cache_tree = sorted_tree_init( NULL, NULL ); + + return ( cache_tree == NULL ); +} + +/********************************************************************** + Add a new REGISTRY_HOOK to the cache. Note that the keyname + is not in the exact format that a SORTED_TREE expects. + *********************************************************************/ + +BOOL reghook_cache_add( REGISTRY_HOOK *hook ) +{ + pstring key; + + if ( !hook ) + return False; + + pstrcpy( key, "\\"); + pstrcat( key, hook->keyname ); + + pstring_sub( key, "\\", "/" ); + + DEBUG(10,("reghook_cache_add: Adding key [%s]\n", key)); + + return sorted_tree_add( cache_tree, key, hook ); +} + +/********************************************************************** + Initialize the cache tree + *********************************************************************/ + +REGISTRY_HOOK* reghook_cache_find( char *keyname ) +{ + char *key; + + if ( !keyname ) + return NULL; + + if ( (key = strdup( keyname )) == NULL ) { + DEBUG(0,("reghook_cache_find: strdup() failed for string [%s] !?!?!\n", + keyname)); + return NULL; + } + + string_sub( key, "\\", "/", 0 ); + + DEBUG(10,("reghook_cache_find: Searching for keyname [%s]\n", key)); + + return sorted_tree_find( cache_tree, key ) ; +} + +/********************************************************************** + Initialize the cache tree + *********************************************************************/ + +void reghook_dump_cache( int debuglevel ) +{ + DEBUG(debuglevel,("reghook_dump_cache: Starting cache dump now...\n")); + + sorted_tree_print_keys( cache_tree, debuglevel ); +} diff --git a/source/registry/reg_frontend.c b/source/registry/reg_db.c similarity index 83% copy from source/registry/reg_frontend.c copy to source/registry/reg_db.c index c4e332ed6b8..a521cdcdd05 100644 --- a/source/registry/reg_frontend.c +++ b/source/registry/reg_db.c @@ -18,20 +18,18 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* Implementation of registry database functions. */ +/* Implementation of internal registry database functions. */ #include "includes.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV - - static TDB_CONTEXT *tdb_reg; /*********************************************************************** - Open the registry database + Open the registry data in the tdb ***********************************************************************/ static BOOL init_registry_data( void ) @@ -43,79 +41,79 @@ static BOOL init_registry_data( void ) pstrcpy( keyname, KEY_HKLM ); subkeys[0] = "SYSTEM"; - if ( !store_reg_keys( keyname, subkeys, 1 )) + if ( !regdb_store_reg_keys( keyname, subkeys, 1 )) return False; pstrcpy( keyname, KEY_HKLM ); pstrcat( keyname, "/SYSTEM" ); subkeys[0] = "CurrentControlSet"; - if ( !store_reg_keys( keyname, subkeys, 1 )) + if ( !regdb_store_reg_keys( keyname, subkeys, 1 )) return False; pstrcpy( keyname, KEY_HKLM ); pstrcat( keyname, "/SYSTEM/CurrentControlSet" ); subkeys[0] = "Control"; subkeys[1] = "services"; - if ( !store_reg_keys( keyname, subkeys, 2 )) + if ( !regdb_store_reg_keys( keyname, subkeys, 2 )) return False; pstrcpy( keyname, KEY_HKLM ); pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control" ); subkeys[0] = "Print"; subkeys[1] = "ProduceOptions"; - if ( !store_reg_keys( keyname, subkeys, 2 )) + if ( !regdb_store_reg_keys( keyname, subkeys, 2 )) return False; +#if 0 /* JERRY */ pstrcpy( keyname, KEY_HKLM ); pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control/Print" ); subkeys[0] = "Environments"; subkeys[1] = "Forms"; subkeys[2] = "Printers"; - if ( !store_reg_keys( keyname, subkeys, 3 )) + if ( !regdb_store_reg_keys( keyname, subkeys, 0 )) return False; +#endif pstrcpy( keyname, KEY_HKLM ); pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control/ProductOptions" ); - if ( !store_reg_keys( keyname, subkeys, 0 )) + if ( !regdb_store_reg_keys( keyname, subkeys, 0 )) return False; pstrcpy( keyname, KEY_HKLM ); pstrcat( keyname, "/SYSTEM/CurrentControlSet/services" ); subkeys[0] = "Netlogon"; - if ( !store_reg_keys( keyname, subkeys, 1 )) + if ( !regdb_store_reg_keys( keyname, subkeys, 1 )) return False; pstrcpy( keyname, KEY_HKLM ); pstrcat( keyname, "/SYSTEM/CurrentControlSet/services/Netlogon" ); subkeys[0] = "parameters"; - if ( !store_reg_keys( keyname, subkeys, 1 )) + if ( !regdb_store_reg_keys( keyname, subkeys, 1 )) return False; pstrcpy( keyname, KEY_HKLM ); pstrcat( keyname, "/SYSTEM/CurrentControlSet/services/Netlogon/parameters" ); - if ( !store_reg_keys( keyname, subkeys, 0 )) + if ( !regdb_store_reg_keys( keyname, subkeys, 0 )) return False; /* HKEY_USER */ pstrcpy( keyname, KEY_HKU ); - if ( !store_reg_keys( keyname, subkeys, 0 ) ) + if ( !regdb_store_reg_keys( keyname, subkeys, 0 ) ) return False; return True; } - /*********************************************************************** Open the registry database ***********************************************************************/ -BOOL init_registry( void ) +BOOL init_registry_db( void ) { static pid_t local_pid; - - + if (tdb_reg && local_pid == sys_getpid()) return True; @@ -144,17 +142,22 @@ BOOL init_registry( void ) } local_pid = sys_getpid(); - + return True; } + + /*********************************************************************** Add subkey strings to the registry tdb under a defined key fmt is the same format as tdb_pack except this function only supports fstrings + + The full path to the registry key is used as database after the + \'s are converted to /'s. ***********************************************************************/ -BOOL store_reg_keys( char *keyname, char **subkeys, uint32 num_subkeys ) +BOOL regdb_store_reg_keys( char *keyname, char **subkeys, uint32 num_subkeys ) { TDB_DATA kbuf, dbuf; char *buffer, *tmpbuf; @@ -215,7 +218,7 @@ done: of null terminated character strings ***********************************************************************/ -int fetch_reg_keys( char* key, char **subkeys ) +int regdb_fetch_reg_keys( char* key, char **subkeys ) { pstring path; uint32 num_items; @@ -263,52 +266,17 @@ done: } /*********************************************************************** - count the number of subkeys dtored in the registry - ***********************************************************************/ - -int fetch_reg_keys_count( char* key ) -{ - pstring path; - uint32 num_items; - TDB_DATA dbuf; - char *buf; - uint32 buflen, len; - - - pstrcpy( path, key ); - - /* convert to key format */ - pstring_sub( path, "\\", "/" ); - - dbuf = tdb_fetch_by_string( tdb_reg, path ); - - buf = dbuf.dptr; - buflen = dbuf.dsize; - - if ( !buf ) { - DEBUG(5,("fetch_reg_keys: Failed to fetch any subkeys for [%s]\n", key)); - return 0; - } - - len = tdb_unpack( buf, buflen, "d", &num_items); - - SAFE_FREE( buf ); - - return num_items; -} - -/*********************************************************************** retreive a specific subkey specified by index. The subkey parameter is assumed to be an fstring. ***********************************************************************/ -BOOL fetch_reg_keys_specific( char* key, char* subkey, uint32 key_index ) +BOOL regdb_fetch_reg_keys_specific( char* key, char** subkey, uint32 key_index ) { int num_subkeys, i; char *subkeys = NULL; char *s; - num_subkeys = fetch_reg_keys( key, &subkeys ); + num_subkeys = regdb_fetch_reg_keys( key, &subkeys ); if ( num_subkeys == -1 ) return False; @@ -316,7 +284,7 @@ BOOL fetch_reg_keys_specific( char* key, char* subkey, uint32 key_index ) for ( i=0; i buflen ) { - /* allocate some extra space */ - if ((tmpbuf = Realloc( buffer, len*2 )) == NULL) { - DEBUG(0,("store_reg_keys: Failed to realloc memory of size [%d]\n", len*2)); - ret = False; - goto done; - } - buffer = tmpbuf; - buflen = len*2; - - len = tdb_pack(buffer+len, buflen-len, "f", subkeys[i]); - } - } - - /* finally write out the data */ - - kbuf.dptr = keyname; - kbuf.dsize = strlen(keyname)+1; - dbuf.dptr = buffer; - dbuf.dsize = len; - if ( tdb_store( tdb_reg, kbuf, dbuf, TDB_REPLACE ) == -1) { - ret = False; - goto done; - } - -done: - SAFE_FREE( buffer ); - return ret; -} - -/*********************************************************************** - Retrieve an array of strings containing subkeys. Memory should be - released by the caller. The subkeys are stored in a catenated string - of null terminated character strings - ***********************************************************************/ - -int fetch_reg_keys( char* key, char **subkeys ) -{ - pstring path; - uint32 num_items; - TDB_DATA dbuf; - char *buf; - uint32 buflen, len; - int i; - char *s; - - - pstrcpy( path, key ); - - /* convert to key format */ - pstring_sub( path, "\\", "/" ); - - dbuf = tdb_fetch_by_string( tdb_reg, path ); - - buf = dbuf.dptr; - buflen = dbuf.dsize; - - if ( !buf ) { - DEBUG(5,("fetch_reg_keys: Failed to fetch any subkeys for [%s]\n", key)); - return 0; - } - - len = tdb_unpack( buf, buflen, "d", &num_items); - if (num_items) { - if ( (*subkeys = (char*)malloc(sizeof(fstring)*num_items)) == NULL ) { - DEBUG(0,("fetch_reg_keys: Failed to malloc memory for subkey array containing [%d] items!\n", - num_items)); - num_items = -1; - goto done; - } - } - - s = *subkeys; - for (i=0; iname, subkeys, num_subkeys ); + +} + +/*********************************************************************** + High level wrapper function for storing registry values + ***********************************************************************/ + +BOOL store_reg_values( REGISTRY_KEY *key, REGISTRY_VALUE **val, uint32 num_values ) +{ + return True; +} + + +/*********************************************************************** + High level wrapper function for enumerating registry subkeys + ***********************************************************************/ + +int fetch_reg_keys( REGISTRY_KEY *key, char **subkeys ) +{ + int num_subkeys; + + if ( key->hook && key->hook->ops && key->hook->ops->subkey_fn ) + num_subkeys = key->hook->ops->subkey_fn( key->name, subkeys ); + else + num_subkeys = regdb_fetch_reg_keys( key->name, subkeys ); + + return num_subkeys; +} + +/*********************************************************************** + High level wrapper function for retreiving a specific registry subkey + given and index. + ***********************************************************************/ + +BOOL fetch_reg_keys_specific( REGISTRY_KEY *key, char** subkey, uint32 key_index ) +{ + BOOL result; + + if ( key->hook && key->hook->ops && key->hook->ops->subkey_specific_fn ) + result = key->hook->ops->subkey_specific_fn( key->name, subkey, key_index ); + else + result = regdb_fetch_reg_keys_specific( key->name, subkey, key_index ); + + return result; +} + + +/*********************************************************************** + High level wrapper function for enumerating registry values + ***********************************************************************/ + +int fetch_reg_values( REGISTRY_KEY *key, REGISTRY_VALUE **val ) +{ + int num_values; + + if ( key->hook && key->hook->ops && key->hook->ops->value_fn ) + num_values = key->hook->ops->value_fn( key->name, val ); + else + num_values = regdb_fetch_reg_values( key->name, val ); + + return num_values; +} + + diff --git a/source/registry/reg_printing.c b/source/registry/reg_printing.c new file mode 100644 index 00000000000..8144110d1f8 --- /dev/null +++ b/source/registry/reg_printing.c @@ -0,0 +1,243 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Implementation of registry virtual views for printing information */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +#define MAX_TOP_LEVEL_KEYS 3 + +/* some symbolic indexes into the top_level_keys */ + +#define KEY_INDEX_ENVIR 0 +#define KEY_INDEX_FORMS 1 +#define KEY_INDEX_PRINTER 2 + +static char *top_level_keys[MAX_TOP_LEVEL_KEYS] = { + "Environments", + "Forms", + "Printers" +}; + +/********************************************************************** + It is safe to assume that every registry path passed into on of + the exported functions here begins with KEY_PRINTING else + these functions would have never been called. This is a small utility + function to strip the beginning of the path and make a copy that the + caller can modify. Note that the caller is responsible for releasing + the memory allocated here. + **********************************************************************/ + +static char* trim_reg_path( char *path ) +{ + char *p; + + p = path + strlen(KEY_PRINTING); + + if ( *p ) + return strdup(p); + else + return NULL; +} + +/********************************************************************** + handle enumeration of subkeys below KEY_PRINTING. + *********************************************************************/ + +static int handle_printing_subpath( char *key, char **subkeys, uint32 index ) +{ + int result = 0; + char *p, *base; + int i; + + + /* + * break off the first part of the path + * topmost base **must** be one of the strings + * in top_level_keys[] + */ + + base = key; + p = strchr( key, '\\' ); + if ( p ) + *p = '\0'; + + for ( i=0; i[%s]\n", key)); + + path = trim_reg_path( key ); + + /* check to see if we are dealing with the top level key */ + + if ( !path ) + top_level = True; + + if ( top_level ) { + if ( ! (*subkeys = malloc( sizeof(top_level_keys) )) ) + goto done; + + num_subkeys = MAX_TOP_LEVEL_KEYS; + memcpy( *subkeys, top_level_keys, sizeof(top_level_keys) ); + } + else + num_subkeys = handle_printing_subpath( path, subkeys, -1 ); + +done: + SAFE_FREE( path ); + return num_subkeys; +} + +/********************************************************************** + Count the registry subkey names given a registry path. + Caller is responsible for freeing memory to **subkey + *********************************************************************/ + +BOOL printing_subkey_specific( char *key, char** subkey, uint32 index ) +{ + char *path; + BOOL top_level = False; + BOOL result = False; + + DEBUG(10,("printing_subkey_specific: key=>[%s], index=>[%d]\n", key, index)); + + path = trim_reg_path( key ); + + /* check to see if we are dealing with the top level key */ + + if ( !path ) + top_level = True; + + + + if ( top_level ) { + + /* make sure the index is in range */ + + if ( !(index < MAX_TOP_LEVEL_KEYS) ) + goto done; + + if ( !(*subkey = malloc( strlen(top_level_keys[index])+1 )) ) + goto done; + + strncpy( *subkey, top_level_keys[index], strlen(top_level_keys[index])+1 ); + + result = True; + } + else { + if ( handle_printing_subpath( path, subkey, index ) != -1 ) + result = True; + } + +done: + SAFE_FREE( path ); + + return result; +} + +/********************************************************************** + Enumerate registry values given a registry path. + Caller is responsible for freeing memory + *********************************************************************/ + +int printing_value_info( char *key, REGISTRY_VALUE **val ) +{ + DEBUG(10,("printing_value_info: key=>[%s]\n", key)); + + return 0; +} + +/********************************************************************** + Stub function which always returns failure since we don't want + people storing printing information directly via regostry calls + (for now at least) + *********************************************************************/ + +BOOL printing_store_subkey( char *key, char **subkeys, uint32 num_subkeys ) +{ + return False; +} + +/********************************************************************** + Stub function which always returns failure since we don't want + people storing printing information directly via regostry calls + (for now at least) + *********************************************************************/ + +BOOL printing_store_value( char *key, REGISTRY_VALUE **val, uint32 num_values ) +{ + return False; +} + +/* + * Table of function pointers for accessing printing data + */ + +REGISTRY_OPS printing_ops = { + printing_subkey_info, + printing_subkey_specific, + printing_value_info, + printing_store_subkey, + printing_store_value +}; + diff --git a/source/rpc_server/srv_reg_nt.c b/source/rpc_server/srv_reg_nt.c index b5511cfceb6..d5b2394b40f 100644 --- a/source/rpc_server/srv_reg_nt.c +++ b/source/rpc_server/srv_reg_nt.c @@ -1,11 +1,11 @@ /* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1997, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, - * Copyright (C) Paul Ashton 1997. - * Copyright (C) Jeremy Allison 2001. - * Copyright (C) Gerald Carter 2002. + * Copyright (C) Andrew Tridgell 1992-1997. + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997. + * Copyright (C) Paul Ashton 1997. + * Copyright (C) Jeremy Allison 2001. + * 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 @@ -33,16 +33,16 @@ ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid()) -static Registry_Key *regkeys_list; +static REGISTRY_KEY *regkeys_list; /****************************************************************** - free() function for Registry_Key + free() function for REGISTRY_KEY *****************************************************************/ static void free_reg_info(void *ptr) { - Registry_Key *info = (Registry_Key*)ptr; + REGISTRY_KEY *info = (REGISTRY_KEY*)ptr; DLIST_REMOVE(regkeys_list, info); @@ -50,12 +50,12 @@ static void free_reg_info(void *ptr) } /****************************************************************** - Find a registry key handle and return a Registry_Key + Find a registry key handle and return a REGISTRY_KEY *****************************************************************/ -static Registry_Key *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd) +static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd) { - Registry_Key *regkey = NULL; + REGISTRY_KEY *regkey = NULL; if(!find_policy_by_hnd(p,hnd,(void **)®key)) { DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: ")); @@ -69,34 +69,87 @@ static Registry_Key *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd) /******************************************************************* Function for open a new registry handle and creating a handle Note that P should be valid & hnd should already have space + + When we open a key, we store the full path to the key as + HK[LM|U]\\\... *******************************************************************/ -static BOOL open_registry_key(pipes_struct *p, POLICY_HND *hnd, char *name, - uint32 access_granted) +static NTSTATUS open_registry_key(pipes_struct *p, POLICY_HND *hnd, REGISTRY_KEY *parent, + char *subkeyname, uint32 access_granted ) { - Registry_Key *regkey = NULL; + REGISTRY_KEY *regkey = NULL; + pstring parent_keyname; + NTSTATUS result = NT_STATUS_OK; + int num_subkeys; + char *subkeys = NULL; + + if ( parent ) { + pstrcpy( parent_keyname, parent->name ); + pstrcat( parent_keyname, "\\" ); + } + else + *parent_keyname = '\0'; + - DEBUG(7,("open_registry_key: name = [%s]\n", name)); + DEBUG(7,("open_registry_key: name = [%s][%s]\n", parent_keyname, subkeyname)); /* All registry keys **must** have a name of non-zero length */ - if (!name || !*name ) - return False; + if (!subkeyname || !*subkeyname ) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; - if ((regkey=(Registry_Key*)malloc(sizeof(Registry_Key))) == NULL) - return False; + if ((regkey=(REGISTRY_KEY*)malloc(sizeof(REGISTRY_KEY))) == NULL) + return NT_STATUS_NO_MEMORY; ZERO_STRUCTP( regkey ); DLIST_ADD( regkeys_list, regkey ); - /* copy the name and obtain a handle */ + /* copy the name */ + + pstrcpy( regkey->name, parent_keyname ); + pstrcat( regkey->name, subkeyname ); + + /* try to use en existing hook. Otherwise, try to lookup our own */ + + if ( parent && parent->hook ) + regkey->hook = parent->hook; + else + regkey->hook = reghook_cache_find( regkey->name ); + + if ( regkey->hook ) { + DEBUG(10,("open_registry_key: Assigned REGISTRY_HOOK to [%s]\n", + regkey->name )); + } + + /* check if the path really exists...num_subkeys should be >= 0 */ - fstrcpy( regkey->name, name ); + num_subkeys = fetch_reg_keys( regkey, &subkeys ); + + /* if the subkey count failed, bail out */ + + if ( num_subkeys == -1 ) { + SAFE_FREE( regkey ); + + /* don't really know what to return here */ + + result = NT_STATUS_ACCESS_DENIED; + } + else { + /* + * This would previously return NT_STATUS_TOO_MANY_SECRETS + * that doesn't sound quite right to me --jerry + */ + + if ( !create_policy_hnd( p, hnd, free_reg_info, regkey ) ) + result = NT_STATUS_OBJECT_NAME_NOT_FOUND; + } DEBUG(7,("open_registry_key: exit\n")); - return create_policy_hnd( p, hnd, free_reg_info, regkey ); + SAFE_FREE( subkeys ); + + return result; } /******************************************************************* @@ -106,7 +159,7 @@ static BOOL open_registry_key(pipes_struct *p, POLICY_HND *hnd, char *name, static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd) { - Registry_Key *regkey = find_regkey_index_by_hnd(p, hnd); + REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd); if ( !regkey ) { DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd))); @@ -122,7 +175,7 @@ static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd) retrieve information about the subkeys *******************************************************************/ -static BOOL get_subkey_information( Registry_Key *key, uint32 *maxnum, uint32 *maxlen ) +static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen ) { int num_subkeys, i; uint32 max_len; @@ -133,7 +186,11 @@ static BOOL get_subkey_information( Registry_Key *key, uint32 *maxnum, uint32 *m if ( !key ) return False; - num_subkeys = fetch_reg_keys( key->name, &subkeys ); + /* first use any registry hook available. + Fall back to tdb if non available */ + + num_subkeys = fetch_reg_keys( key, &subkeys ); + if ( num_subkeys == -1 ) return False; @@ -161,28 +218,36 @@ static BOOL get_subkey_information( Registry_Key *key, uint32 *maxnum, uint32 *m Samba tdb's (such as ntdrivers.tdb). *******************************************************************/ -static BOOL get_value_information( Registry_Key *key, uint32 *maxnum, +static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen, uint32 *maxsize ) { + REGISTRY_VALUE *val = NULL; + uint32 i, sizemax, lenmax; + int num_values; + if ( !key ) return False; - /* Hard coded key names first */ - /* nothing has valuies right now */ + num_values = fetch_reg_values( key, &val ); + + if ( num_values == -1 ) + return False; + + + lenmax = sizemax = 0; - *maxnum = 0; - *maxlen = 0; - *maxsize = 0; + for ( i=0; ipol, KEY_HKLM, 0x0)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - - return NT_STATUS_OK; + return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, 0x0 ); } /******************************************************************* @@ -220,10 +282,7 @@ NTSTATUS _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM * NTSTATUS _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HKU *q_u, REG_R_OPEN_HKU *r_u) { - if (!open_registry_key(p, &r_u->pol, KEY_HKU, 0x0)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - - return NT_STATUS_OK; + return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, 0x0 ); } /******************************************************************* @@ -234,9 +293,8 @@ NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTR { POLICY_HND pol; fstring name; - pstring path; - int num_subkeys; - Registry_Key *key = find_regkey_index_by_hnd(p, &q_u->pol); + REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->pol); + NTSTATUS result; DEBUG(5,("reg_open_entry: Enter\n")); @@ -244,26 +302,14 @@ NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTR return NT_STATUS_INVALID_HANDLE; rpcstr_pull(name,q_u->uni_name.buffer,sizeof(name),q_u->uni_name.uni_str_len*2,0); - - /* store the full path in the regkey_list */ - pstrcpy( path, key->name ); - pstrcat( path, "\\" ); - pstrcat( path, name ); - - DEBUG(5,("reg_open_entry: %s\n", path)); - - /* do a check on the name, here */ + DEBUG(5,("reg_open_entry: Enter\n")); - if ( (num_subkeys=fetch_reg_keys_count( path )) == -1 ) - return NT_STATUS_ACCESS_DENIED; - - if (!open_registry_key(p, &pol, path, 0x0)) - return NT_STATUS_TOO_MANY_SECRETS; - - init_reg_r_open_entry(r_u, &pol, NT_STATUS_OK); + result = open_registry_key( p, &pol, key, name, 0x0 ); + + init_reg_r_open_entry( r_u, &pol, result ); - DEBUG(5,("reg_open_entry: Exitn")); + DEBUG(5,("reg_open_entry: Exit\n")); return r_u->status; } @@ -280,7 +326,7 @@ NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u) UNISTR2 *uni_key = NULL; BUFFER2 *buf = NULL; fstring name; - Registry_Key *key = find_regkey_index_by_hnd( p, &q_u->pol ); + REGISTRY_KEY *key = find_regkey_index_by_hnd( p, &q_u->pol ); DEBUG(5,("_reg_info: Enter\n")); @@ -346,7 +392,7 @@ NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u) NTSTATUS _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u) { NTSTATUS status = NT_STATUS_OK; - Registry_Key *regkey = find_regkey_index_by_hnd( p, &q_u->pol ); + REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol ); DEBUG(5,("_reg_query_key: Enter\n")); @@ -358,6 +404,7 @@ NTSTATUS _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY * if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) ) return NT_STATUS_ACCESS_DENIED; + r_u->sec_desc = 0x00000078; /* size for key's sec_desc */ @@ -379,7 +426,7 @@ NTSTATUS _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY * NTSTATUS _reg_unknown_1a(pipes_struct *p, REG_Q_UNKNOWN_1A *q_u, REG_R_UNKNOWN_1A *r_u) { NTSTATUS status = NT_STATUS_OK; - Registry_Key *regkey = find_regkey_index_by_hnd( p, &q_u->pol ); + REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol ); DEBUG(5,("_reg_unknown_1a: Enter\n")); @@ -401,8 +448,8 @@ NTSTATUS _reg_unknown_1a(pipes_struct *p, REG_Q_UNKNOWN_1A *q_u, REG_R_UNKNOWN_1 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 ); - fstring subkey; + REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol ); + char *subkey; DEBUG(5,("_reg_enum_key: Enter\n")); @@ -412,9 +459,9 @@ NTSTATUS _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name)); - if ( !fetch_reg_keys_specific( regkey->name, subkey, q_u->key_index ) ) + if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) ) { - status = werror_to_ntstatus( WERR_NO_MORE_ITEMS ); + status = NT_STATUS_NO_MORE_ENTRIES; goto done; } @@ -427,6 +474,7 @@ NTSTATUS _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u DEBUG(5,("_reg_enum_key: Exit\n")); done: + SAFE_FREE( subkey ); return status; } diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk index c701ed41cda..eef7180e72b 100644 --- a/source/script/mkproto.awk +++ b/source/script/mkproto.awk @@ -142,7 +142,7 @@ END { gotstart = 1; } - if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject/ ) { + if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject|^SORTED_TREE|^REGISTRY_HOOK/ ) { gotstart = 1; } -- 2.11.4.GIT