s3:registry: move reg_objects.h to registry/ and use it only where needed
[kai/samba.git] / source3 / registry / reg_eventlog.c
index b20eb046db8034428140b31044b2458e92187c4d..6bedf4635ebdc536a2db80cae9693f56b1b5ed4a 100644 (file)
@@ -1,11 +1,14 @@
+
 /* 
  *  Unix SMB/CIFS implementation.
  *  Virtual Windows Registry Layer
- *  Copyright (C) Marcin Krzysztof Porwit    2005.
+ *  Copyright (C) Marcin Krzysztof Porwit    2005,
+ *  Copyright (C) Brian Moran                2005.
+ *  Copyright (C) Gerald (Jerry) Carter      2005.
  *  
  *  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
+ *  the Free Software Foundation; either version 3 of the License, or
  *  (at your option) any later version.
  *  
  *  This program is distributed in the hope that it will be useful,
  *  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.
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
+
 #include "includes.h"
+#include "registry.h"
+#include "reg_backend_db.h"
+#include "reg_eventlog.h"
+#include "reg_objects.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
 
 /**********************************************************************
- handle enumeration of values AT KEY_EVENTLOG
- *********************************************************************/
-static int eventlog_topkey_values( char *key, REGVAL_CTR *val )
+ for an eventlog, add in the default values
+*********************************************************************/
+
+bool eventlog_init_keys(void)
 {
-    int                num_values = 0;
-    char               *keystr, *key2 = NULL;
-    char               *base, *new_path;
-    fstring            evtlogname; 
-    UNISTR2            data;
-    int             iDisplayNameId;
-    int             iMaxSize;
-    
-    /* 
-     *  TODO - callout to get these values...
-     */
-    
-    if ( key ) 
-    {
-       key2 = SMB_STRDUP( key );
-       keystr = key2;
-       reg_split_path( keystr, &base, &new_path );
-       
-       iDisplayNameId = 0x00000100;
-       iMaxSize=        0x00080000;
-       
-       fstrcpy( evtlogname, base );
-       DEBUG(10,("eventlog_topkey_values: subkey root=> [%s] subkey path=>[%s]\n", base,new_path));
-       
-       if ( !new_path ) 
-       {
-           iDisplayNameId = 0x01;
-           regval_ctr_addvalue( val, "ErrorControl",    REG_DWORD, (char*)&iDisplayNameId,       sizeof(int) ); 
-           
-           init_unistr2( &data, "EventLog", UNI_STR_TERMINATE);
-           regval_ctr_addvalue( val, "DisplayName",             REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-           
-           num_values = regval_ctr_numvals( val );     
-           
-           
-           num_values = 0;
+       /* Find all of the eventlogs, add keys for each of them */
+       const char **elogs = lp_eventlog_list();
+       char *evtlogpath = NULL;
+       char *evtfilepath = NULL;
+       struct regsubkey_ctr *subkeys;
+       struct regval_ctr *values;
+       uint32 uiMaxSize;
+       uint32 uiRetention;
+       uint32 uiCategoryCount;
+       DATA_BLOB data;
+       TALLOC_CTX *ctx = talloc_tos();
+       WERROR werr;
+
+       while (elogs && *elogs) {
+               werr = regsubkey_ctr_init(ctx, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG( 0, ( "talloc() failure!\n" ) );
+                       return False;
+               }
+               regdb_fetch_keys(KEY_EVENTLOG, subkeys);
+               regsubkey_ctr_addkey( subkeys, *elogs );
+               if ( !regdb_store_keys( KEY_EVENTLOG, subkeys ) ) {
+                       TALLOC_FREE(subkeys);
+                       return False;
+               }
+               TALLOC_FREE(subkeys);
+
+               /* add in the key of form KEY_EVENTLOG/Application */
+               DEBUG( 5,
+                      ( "Adding key of [%s] to path of [%s]\n", *elogs,
+                        KEY_EVENTLOG ) );
+
+               evtlogpath = talloc_asprintf(ctx, "%s\\%s",
+                         KEY_EVENTLOG, *elogs);
+               if (!evtlogpath) {
+                       return false;
+               }
+               /* add in the key of form KEY_EVENTLOG/Application/Application */
+               DEBUG( 5,
+                      ( "Adding key of [%s] to path of [%s]\n", *elogs,
+                        evtlogpath ) );
+               werr = regsubkey_ctr_init(ctx, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG( 0, ( "talloc() failure!\n" ) );
+                       return False;
+               }
+               regdb_fetch_keys( evtlogpath, subkeys );
+               regsubkey_ctr_addkey( subkeys, *elogs );
+
+               if ( !regdb_store_keys( evtlogpath, subkeys ) ) {
+                       TALLOC_FREE(subkeys);
+                       return False;
+               }
+               TALLOC_FREE( subkeys );
+
+               /* now add the values to the KEY_EVENTLOG/Application form key */
+
+               werr = regval_ctr_init(ctx, &values);
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG( 0, ( "talloc() failure!\n" ) );
+                       return False;
+               }
+               DEBUG( 5,
+                      ( "Storing values to eventlog path of [%s]\n",
+                        evtlogpath ) );
+               regdb_fetch_values( evtlogpath, values );
+
+
+               if (!regval_ctr_key_exists(values, "MaxSize")) {
+
+                       /* assume we have none, add them all */
+
+                       /* hard code some initial values */
+
+                       /* uiDisplayNameId = 0x00000100; */
+                       uiMaxSize = 0x00080000;
+                       uiRetention = 0x93A80;
+
+                       regval_ctr_addvalue(values, "MaxSize", REG_DWORD,
+                                            (uint8 *)&uiMaxSize,
+                                            sizeof(uint32));
+
+                       regval_ctr_addvalue(values, "Retention", REG_DWORD,
+                                            (uint8 *)&uiRetention,
+                                            sizeof(uint32));
+
+                       regval_ctr_addvalue_sz(values, "PrimaryModule", *elogs);
+                       push_reg_sz(talloc_tos(), &data, *elogs);
+
+                       regval_ctr_addvalue(values, "Sources", REG_MULTI_SZ,
+                                            data.data,
+                                            data.length);
+
+                       evtfilepath = talloc_asprintf(ctx,
+                                       "%%SystemRoot%%\\system32\\config\\%s.tdb",
+                                       *elogs);
+                       if (!evtfilepath) {
+                               TALLOC_FREE(values);
+                       }
+                       push_reg_sz(talloc_tos(), &data, evtfilepath);
+                       regval_ctr_addvalue(values, "File", REG_EXPAND_SZ, data.data,
+                                            data.length);
+                       regdb_store_values(evtlogpath, values);
+
+               }
+
+               TALLOC_FREE(values);
+
+               /* now do the values under KEY_EVENTLOG/Application/Application */
+               TALLOC_FREE(evtlogpath);
+               evtlogpath = talloc_asprintf(ctx, "%s\\%s\\%s",
+                         KEY_EVENTLOG, *elogs, *elogs);
+               if (!evtlogpath) {
+                       return false;
+               }
+
+               werr = regval_ctr_init(ctx, &values);
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG( 0, ( "talloc() failure!\n" ) );
+                       return False;
+               }
+               DEBUG( 5,
+                      ( "Storing values to eventlog path of [%s]\n",
+                        evtlogpath));
+               regdb_fetch_values(evtlogpath, values);
+               if (!regval_ctr_key_exists( values, "CategoryCount")) {
+
+                       /* hard code some initial values */
+
+                       uiCategoryCount = 0x00000007;
+                       regval_ctr_addvalue( values, "CategoryCount",
+                                            REG_DWORD,
+                                            (uint8 *) &uiCategoryCount,
+                                            sizeof( uint32 ) );
+                       push_reg_sz(talloc_tos(), &data,
+                                     "%SystemRoot%\\system32\\eventlog.dll");
+
+                       regval_ctr_addvalue( values, "CategoryMessageFile",
+                                            REG_EXPAND_SZ,
+                                            data.data,
+                                            data.length);
+                       regdb_store_values( evtlogpath, values );
+               }
+               TALLOC_FREE(values);
+               elogs++;
        }
-    }
-    
-    SAFE_FREE( key2 ); 
-    return num_values;
-}
 
-/**********************************************************************
- handle enumeration of values below KEY_EVENTLOG\<Eventlog>
- *********************************************************************/
-static int eventlog_subkey_values( char *key, REGVAL_CTR *val )
-{
-    int        num_values = 0;
-    char       *keystr, *key2 = NULL;
-    char       *base, *new_path;
-    fstring            evtlogname; 
-    UNISTR2            data;
-    int         iDisplayNameId;
-    int         iMaxSize;
-    int         iRetention;
-    
-    /* 
-     *  TODO - callout to get these values...
-     */
-    
-    if ( !key ) 
-       return num_values;
-    
-    key2 = SMB_STRDUP( key );
-    keystr = key2;
-    reg_split_path( keystr, &base, &new_path );
-    
-    iDisplayNameId = 0x00000100;
-    /* MaxSize is limited to 0xFFFF0000 (UINT_MAX - USHRT_MAX) as per MSDN documentation */
-    iMaxSize=        0xFFFF0000;
-    /* records in the samba log are not overwritten */
-    iRetention =     0xFFFFFFFF;
-    
-    fstrcpy( evtlogname, base );
-    DEBUG(10,("eventlog_subpath_values_printer: eventlogname [%s]\n", base));
-    DEBUG(10,("eventlog_subpath_values_printer: new_path [%s]\n", new_path));
-    if ( !new_path ) 
-    {
-#if 0
-       regval_ctr_addvalue( val, "DisplayNameId",    REG_DWORD, (char*)&iDisplayNameId,       sizeof(int) ); 
-       
-       init_unistr2( &data, "%SystemRoot%\\system32\\els.dll", UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "DisplayNameFile",             REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-#endif
-       regval_ctr_addvalue( val, "MaxSize",          REG_DWORD, (char*)&iMaxSize, sizeof(int));
-       regval_ctr_addvalue( val, "Retention",  REG_DWORD, (char *)&iRetention, sizeof(int));
-#if 0
-       init_unistr2( &data, lp_logfile(), UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "File",             REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-#endif
-       init_unistr2( &data, base, UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "PrimaryModule",         REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-       
-       init_unistr2( &data, base, UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "Sources",          REG_MULTI_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-       
-       num_values = regval_ctr_numvals( val ); 
-       
-    } 
-    else
-    {
-       iDisplayNameId = 0x07;
-       regval_ctr_addvalue( val, "CategoryCount",    REG_DWORD, (char*)&iDisplayNameId,       sizeof(int) ); 
-       
-       init_unistr2( &data, "%SystemRoot%\\system32\\eventlog.dll", UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "CategoryMessageFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-       
-       num_values = regval_ctr_numvals( val ); 
-       
-       num_values = 0;
-    }
-    
-    SAFE_FREE( key2 ); 
-    return num_values;
+       return true;
 }
 
+/*********************************************************************
+ for an eventlog, add in a source name. If the eventlog doesn't
+ exist (not in the list) do nothing.   If a source for the log
+ already exists, change the information (remove, replace)
+*********************************************************************/
 
-/**********************************************************************
- It is safe to assume that every registry path passed into on of 
- the exported functions here begins with KEY_EVENTLOG 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_eventlog_reg_path( const char *path )
+bool eventlog_add_source( const char *eventlog, const char *sourcename,
+                         const char *messagefile )
 {
-       const char *p;
-       uint16 key_len = strlen(KEY_EVENTLOG);
-       
-       /* 
-        * sanity check...this really should never be True.
-        * It is only here to prevent us from accessing outside
-        * the path buffer in the extreme case.
-        */
-       
-       if ( strlen(path) < key_len ) {
-               DEBUG(0,("trim_reg_path: Registry path too short! [%s]\n", path));
-               DEBUG(0,("trim_reg_path: KEY_EVENTLOG => [%s]!\n", KEY_EVENTLOG));
-               return NULL;
+       /* Find all of the eventlogs, add keys for each of them */
+       /* need to add to the value KEY_EVENTLOG/<eventlog>/Sources string (Creating if necessary)
+          need to add KEY of source to KEY_EVENTLOG/<eventlog>/<source> */
+
+       const char **elogs = lp_eventlog_list(  );
+       const char **wrklist, **wp;
+       char *evtlogpath = NULL;
+       struct regsubkey_ctr *subkeys;
+       struct regval_ctr *values;
+       struct regval_blob *rval;
+       int ii = 0;
+       bool already_in;
+       int i;
+       int numsources = 0;
+       TALLOC_CTX *ctx = talloc_tos();
+       WERROR werr;
+       DATA_BLOB blob;
+
+       if (!elogs) {
+               return False;
        }
-       
-       
-       p = path + strlen( KEY_EVENTLOG );
-       
-       if ( *p == '\\' )
-               p++;
-       
-       if ( *p )
-               return SMB_STRDUP(p);
-       else
-               return NULL;
-}
-/**********************************************************************
- Enumerate registry subkey names given a registry path.  
- Caller is responsible for freeing memory to **subkeys
- *********************************************************************/
-static int eventlog_subkey_info( const char *key, REGSUBKEY_CTR *subkey_ctr )
-{
-    char       *path;
-    BOOL               top_level = False;
-    int                num_subkeys = 0;
-    const char        **evtlog_list;
-    
-    path = trim_eventlog_reg_path( key );
-    DEBUG(10,("eventlog_subkey_info: entire key=>[%s] SUBkey=>[%s]\n", key,path));     
-    
-    /* check to see if we are dealing with the top level key */
-    num_subkeys = 0;
-    
-    if ( !path )
-       top_level = True;
-    
-    num_subkeys = 0;
-    if ( !(evtlog_list = lp_eventlog_list()) ) {
-       SAFE_FREE(path);
-       return num_subkeys;
-    }
-
-    
-    if ( top_level )
-    { 
-        /* todo - get the eventlog subkey values from the smb.conf file
-          for ( num_subkeys=0; num_subkeys<MAX_TOP_LEVEL_KEYS; num_subkeys++ )
-          regsubkey_ctr_addkey( subkey_ctr, top_level_keys[num_subkeys] ); */
-       DEBUG(10,("eventlog_subkey_info: Adding eventlog subkeys from globals\n"));     
-       /* TODO - make this  from the globals.szEventLogs list */
-       
-       while (*evtlog_list) 
-       {
-           DEBUG(10,("eventlog_subkey_info: Adding subkey =>[%s]\n",*evtlog_list));    
-           regsubkey_ctr_addkey( subkey_ctr, *evtlog_list);
-           evtlog_list++;
-           num_subkeys++;
+
+       for ( i = 0; elogs[i]; i++ ) {
+               if ( strequal( elogs[i], eventlog ) )
+                       break;
        }
-    }
-    else 
-    {
-       while (*evtlog_list && (0==num_subkeys) ) 
-       {
-           if (0 == StrCaseCmp(path,*evtlog_list)) 
-           {
-               DEBUG(10,("eventlog_subkey_info: Adding subkey [%s] for key =>[%s]\n",path,*evtlog_list));      
-               regsubkey_ctr_addkey( subkey_ctr, *evtlog_list);
-               num_subkeys = 1;
-           }
-           evtlog_list++;
+
+       if ( !elogs[i] ) {
+               DEBUG( 0,
+                      ( "Eventlog [%s] not found in list of valid event logs\n",
+                        eventlog ) );
+               return false;   /* invalid named passed in */
        }
-       
-       if (0==num_subkeys) 
-           DEBUG(10,("eventlog_subkey_info: No match on SUBkey=>[%s]\n", path));
-    }
-    
-    SAFE_FREE( path );
-    return num_subkeys;
-}
 
-/**********************************************************************
- Enumerate registry values given a registry path.  
- Caller is responsible for freeing memory 
- *********************************************************************/
+       /* have to assume that the evenlog key itself exists at this point */
+       /* add in a key of [sourcename] under the eventlog key */
 
-static int eventlog_value_info( const char *key, REGVAL_CTR *val )
-{
-       char            *path;
-       BOOL            top_level = False;
-       int             num_values = 0;
-       
-       DEBUG(10,("eventlog_value_info: key=>[%s]\n", key));
-       
-       path = trim_eventlog_reg_path( key );
-       
-       /* check to see if we are dealing with the top level key */
-       
-       if ( !path )
-           top_level = True;
-       if ( top_level )
-           num_values = eventlog_topkey_values(path,val);
-       else 
-       {
-           DEBUG(10,("eventlog_value_info: SUBkey=>[%s]\n", path));
-           num_values = eventlog_subkey_values(path,val);
+       /* todo add to Sources */
+
+       werr = regval_ctr_init(ctx, &values);
+       if(!W_ERROR_IS_OK(werr)) {
+               DEBUG( 0, ( "talloc() failure!\n" ));
+               return false;
        }
-       return num_values;
-}
 
-/**********************************************************************
- Stub function which always returns failure since we don't want
- people storing eventlog information directly via registry calls
- (for now at least)
- *********************************************************************/
-static BOOL eventlog_store_subkey( const char *key, REGSUBKEY_CTR *subkeys )
-{
-       return False;
-}
+       evtlogpath = talloc_asprintf(ctx, "%s\\%s", KEY_EVENTLOG, eventlog);
+       if (!evtlogpath) {
+               TALLOC_FREE(values);
+               return false;
+       }
 
-/**********************************************************************
- Stub function which always returns failure since we don't want
- people storing eventlog information directly via registry calls
- (for now at least)
- *********************************************************************/
-static BOOL eventlog_store_value( const char *key, REGVAL_CTR *val )
-{
-       return False;
-}
+       regdb_fetch_values( evtlogpath, values );
 
-/* 
- * Table of function pointers for accessing eventlog data
- */
-REGISTRY_OPS eventlog_ops = {
-       eventlog_subkey_info,
-       eventlog_value_info,
-       eventlog_store_subkey,
-       eventlog_store_value,
-       NULL
-};
+
+       if ( !( rval = regval_ctr_getvalue( values, "Sources" ) ) ) {
+               DEBUG( 0, ( "No Sources value for [%s]!\n", eventlog ) );
+               return False;
+       }
+       /* perhaps this adding a new string to a multi_sz should be a fn? */
+       /* check to see if it's there already */
+
+       if ( regval_type(rval) != REG_MULTI_SZ ) {
+               DEBUG( 0,
+                      ( "Wrong type for Sources, should be REG_MULTI_SZ\n" ) );
+               return False;
+       }
+       /* convert to a 'regulah' chars to do some comparisons */
+
+       already_in = False;
+       wrklist = NULL;
+       dump_data(1, regval_data_p(rval), regval_size(rval));
+
+       blob = data_blob_const(regval_data_p(rval), regval_size(rval));
+       if (!pull_reg_multi_sz(talloc_tos(), &blob, &wrklist)) {
+               return false;
+       }
+
+       for (ii=0; wrklist[ii]; ii++) {
+               numsources++;
+       }
+
+       if (numsources > 0) {
+               /* see if it's in there already */
+               wp = wrklist;
+
+               while (wp && *wp ) {
+                       if ( strequal( *wp, sourcename ) ) {
+                               DEBUG( 5,
+                                      ( "Source name [%s] already in list for [%s] \n",
+                                        sourcename, eventlog ) );
+                               already_in = True;
+                               break;
+                       }
+                       wp++;
+               }
+       } else {
+               DEBUG( 3,
+                      ( "Nothing in the sources list, this might be a problem\n" ) );
+       }
+
+       wp = wrklist;
+
+       if ( !already_in ) {
+               /* make a new list with an additional entry; copy values, add another */
+               wp = TALLOC_ARRAY(ctx, const char *, numsources + 2 );
+
+               if ( !wp ) {
+                       DEBUG( 0, ( "talloc() failed \n" ) );
+                       return False;
+               }
+               memcpy( wp, wrklist, sizeof( char * ) * numsources );
+               *( wp + numsources ) = ( char * ) sourcename;
+               *( wp + numsources + 1 ) = NULL;
+               if (!push_reg_multi_sz(ctx, &blob, wp)) {
+                       return false;
+               }
+               dump_data( 1, blob.data, blob.length);
+               regval_ctr_addvalue( values, "Sources", REG_MULTI_SZ,
+                                    blob.data, blob.length);
+               regdb_store_values( evtlogpath, values );
+               data_blob_free(&blob);
+       } else {
+               DEBUG( 3,
+                      ( "Source name [%s] found in existing list of sources\n",
+                        sourcename ) );
+       }
+       TALLOC_FREE(values);
+       TALLOC_FREE(wrklist);   /*  */
+
+       werr = regsubkey_ctr_init(ctx, &subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG( 0, ( "talloc() failure!\n" ) );
+               return False;
+       }
+       TALLOC_FREE(evtlogpath);
+       evtlogpath = talloc_asprintf(ctx, "%s\\%s", KEY_EVENTLOG, eventlog );
+       if (!evtlogpath) {
+               TALLOC_FREE(subkeys);
+               return false;
+       }
+
+       regdb_fetch_keys( evtlogpath, subkeys );
+
+       if ( !regsubkey_ctr_key_exists( subkeys, sourcename ) ) {
+               DEBUG( 5,
+                      ( " Source name [%s] for eventlog [%s] didn't exist, adding \n",
+                        sourcename, eventlog ) );
+               regsubkey_ctr_addkey( subkeys, sourcename );
+               if ( !regdb_store_keys( evtlogpath, subkeys ) )
+                       return False;
+       }
+       TALLOC_FREE(subkeys);
+
+       /* at this point KEY_EVENTLOG/<eventlog>/<sourcename> key is in there. Now need to add EventMessageFile */
+
+       /* now allocate room for the source's subkeys */
+
+       werr = regsubkey_ctr_init(ctx, &subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG( 0, ( "talloc() failure!\n" ) );
+               return False;
+       }
+       TALLOC_FREE(evtlogpath);
+       evtlogpath = talloc_asprintf(ctx, "%s\\%s\\%s",
+                 KEY_EVENTLOG, eventlog, sourcename);
+       if (!evtlogpath) {
+               TALLOC_FREE(subkeys);
+               return false;
+       }
+
+       regdb_fetch_keys( evtlogpath, subkeys );
+
+       /* now add the values to the KEY_EVENTLOG/Application form key */
+       werr = regval_ctr_init(ctx, &values);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG( 0, ( "talloc() failure!\n" ) );
+               return False;
+       }
+       DEBUG( 5,
+              ( "Storing EventMessageFile [%s] to eventlog path of [%s]\n",
+                messagefile, evtlogpath ) );
+
+       regdb_fetch_values( evtlogpath, values );
+
+       regval_ctr_addvalue_sz(values, "EventMessageFile", messagefile);
+       regdb_store_values( evtlogpath, values );
+
+       TALLOC_FREE(values);
+
+       return True;
+}