s3:loadparm: add lp_local_ptr() that operates on a service struct
[ira/wip.git] / source3 / param / loadparm.c
index f61d0d8fdc14a8fa41b7c458187a1a567d92c27e..43fd9d9d3a3cc065b1246863339052be25d35e0a 100644 (file)
@@ -52,6 +52,7 @@
  */
 
 #include "includes.h"
+#include "printing.h"
 
 bool bLoaded = False;
 
@@ -70,9 +71,16 @@ extern userdom_struct current_user_info;
 #define HOMES_NAME "homes"
 #endif
 
+/* the special value for the include parameter
+ * to be interpreted not as a file name but to
+ * trigger loading of the global smb.conf options
+ * from registry. */
+#ifndef INCLUDE_REGISTRY_NAME
+#define INCLUDE_REGISTRY_NAME "registry"
+#endif
+
 static bool in_client = False;         /* Not in the client by default */
 static struct smbconf_csn conf_last_csn;
-static struct smbconf_ctx *conf_ctx = NULL;
 
 #define CONFIG_BACKEND_FILE 0
 #define CONFIG_BACKEND_REGISTRY 1
@@ -90,9 +98,8 @@ extern int extra_time_offset;
 
 static bool defaults_saved = False;
 
-typedef struct _param_opt_struct param_opt_struct;
-struct _param_opt_struct {
-       param_opt_struct *prev, *next;
+struct param_opt_struct {
+       struct param_opt_struct *prev, *next;
        char *key;
        char *value;
        char **list;
@@ -188,8 +195,7 @@ struct global {
        bool bWinbindOfflineLogon;
        bool bWinbindNormalizeNames;
        bool bWinbindRpcOnly;
-       char **szIdmapDomains;
-       char **szIdmapBackend; /* deprecated */
+       char *szIdmapBackend;
        char *szIdmapAllocBackend;
        char *szAddShareCommand;
        char *szChangeShareCommand;
@@ -235,6 +241,7 @@ struct global {
        int map_to_guest;
        int oplock_break_wait_time;
        int winbind_cache_time;
+       int winbind_reconnect_delay;
        int winbind_max_idle_children;
        char **szWinbindNssInfo;
        int iLockSpinTime;
@@ -256,6 +263,7 @@ struct global {
        int ldap_passwd_sync;
        int ldap_replication_sleep;
        int ldap_timeout; /* This is initialised in init_globals */
+       int ldap_connection_timeout;
        int ldap_page_size;
        bool ldap_delete_dn;
        bool bMsAddPrinterWizard;
@@ -266,6 +274,8 @@ struct global {
        int  iPreferredMaster;
        int iDomainMaster;
        bool bDomainLogons;
+       char **szInitLogonDelayedHosts;
+       int InitLogonDelay;
        bool bEncryptPasswords;
        bool bUpdateEncrypt;
        int  clientSchannel;
@@ -330,7 +340,8 @@ struct global {
        bool bResetOnZeroVC;
        int iKeepalive;
        int iminreceivefile;
-       param_opt_struct *param_opt;
+       struct param_opt_struct *param_opt;
+       int cups_connection_timeout;
 };
 
 static struct global Globals;
@@ -414,6 +425,7 @@ struct service {
        bool bHideUnReadable;
        bool bHideUnWriteableFiles;
        bool bBrowseable;
+       bool bAccessBasedShareEnum;
        bool bAvailable;
        bool bRead_only;
        bool bNo_set_dir;
@@ -474,7 +486,7 @@ struct service {
        int iMap_readonly;
        int iDirectoryNameCacheSize;
        int ismb_encrypt;
-       param_opt_struct *param_opt;
+       struct param_opt_struct *param_opt;
 
        char dummy[3];          /* for alignment */
 };
@@ -557,6 +569,7 @@ static struct service sDefault = {
        False,                  /* bHideUnReadable */
        False,                  /* bHideUnWriteableFiles */
        True,                   /* bBrowseable */
+       False,                  /* bAccessBasedShareEnum */
        True,                   /* bAvailable */
        True,                   /* bRead_only */
        True,                   /* bNo_set_dir */
@@ -658,6 +671,8 @@ static void set_server_role(void);
 static void set_default_server_announce_type(void);
 static void set_allowed_client_auth(void);
 
+static void *lp_local_ptr(struct service *service, void *ptr);
+
 static const struct enum_list enum_protocol[] = {
        {PROTOCOL_NT1, "NT1"},
        {PROTOCOL_LANMAN2, "LANMAN2"},
@@ -1499,7 +1514,7 @@ static struct parm_struct parm_table[] = {
                .ptr            = &sDefault.bAclGroupControl,
                .special        = NULL,
                .enum_list      = NULL,
-               .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED,
+               .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
        },
        {
                .label          = "acl map full control",
@@ -2585,6 +2600,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
        },
+       {
+               .label          = "cups connection timeout",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.cups_connection_timeout,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
        {
                .label          = "iprint server",
                .type           = P_STRING,
@@ -3183,6 +3207,23 @@ static struct parm_struct parm_table[] = {
                .flags          = FLAG_ADVANCED,
        },
 
+       {
+               .label          = "init logon delayed hosts",
+               .type           = P_LIST,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.szInitLogonDelayedHosts,
+               .flags          = FLAG_ADVANCED,
+       },
+
+       {
+               .label          = "init logon delay",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.InitLogonDelay,
+               .flags          = FLAG_ADVANCED,
+
+       },
+
        {N_("Browse Options"), P_SEP, P_SEPARATOR},
 
        {
@@ -3266,6 +3307,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
        },
+       {
+               .label          = "access based share enum",
+               .type           = P_BOOL,
+               .p_class        = P_LOCAL,
+               .ptr            = &sDefault.bAccessBasedShareEnum,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE
+       },
        {
                .label          = "browsable",
                .type           = P_BOOL,
@@ -3554,6 +3604,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
+       {
+               .label          = "ldap connection timeout",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.ldap_connection_timeout,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
        {
                .label          = "ldap page size",
                .type           = P_INTEGER,
@@ -4220,18 +4279,9 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
-       {
-               .label          = "idmap domains",
-               .type           = P_LIST,
-               .p_class        = P_GLOBAL,
-               .ptr            = &Globals.szIdmapDomains,
-               .special        = NULL,
-               .enum_list      = NULL,
-               .flags          = FLAG_ADVANCED,
-       },
        {
                .label          = "idmap backend",
-               .type           = P_LIST,
+               .type           = P_STRING,
                .p_class        = P_GLOBAL,
                .ptr            = &Globals.szIdmapBackend,
                .special        = NULL,
@@ -4337,6 +4387,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
+       {
+               .label          = "winbind reconnect delay",
+               .type           = P_INTEGER,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.winbind_reconnect_delay,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
        {
                .label          = "winbind enum users",
                .type           = P_BOOL,
@@ -4526,6 +4585,54 @@ static void init_printer_values(struct service *pService)
        }
 }
 
+/**
+ * Free the allocated data for one parameter for a given share.
+ */
+static void free_parameter(int snum, struct parm_struct parm)
+{
+       void *parm_ptr;
+
+       if (parm.ptr == NULL); {
+               return;
+       }
+
+       if (snum < 0) {
+               parm_ptr = parm.ptr;
+       } else if (parm.p_class != P_LOCAL) {
+               return;
+       } else {
+               parm_ptr = lp_local_ptr_by_snum(snum, parm.ptr);
+       }
+
+       if ((parm.type == P_STRING) ||
+           (parm.type == P_USTRING))
+       {
+               string_free((char**)parm_ptr);
+       } else if (parm.type == P_LIST) {
+               TALLOC_FREE(*((char***)parm_ptr));
+       }
+}
+
+/**
+ * Free the allocated parameter data for a share.
+ */
+static void free_parameters(int snum)
+{
+       uint32_t i;
+
+       for (i=0; parm_table[i].label; i++) {
+               free_parameter(snum, parm_table[i]);
+       }
+}
+
+/**
+ * Free the allocated global parameters.
+ */
+static void free_global_parameters(void)
+{
+       free_parameters(GLOBAL_SECTION_SNUM);
+}
+
 /***************************************************************************
  Initialise the global parameter structure.
 ***************************************************************************/
@@ -4550,14 +4657,7 @@ static void init_globals(bool first_time_only)
                }
                done_init = True;
        } else {
-               for (i = 0; parm_table[i].label; i++) {
-                       if ((parm_table[i].type == P_STRING ||
-                            parm_table[i].type == P_USTRING) &&
-                           parm_table[i].ptr)
-                       {
-                               string_free((char **)parm_table[i].ptr);
-                       }
-               }
+               free_global_parameters();
        }
 
        memset((void *)&Globals, '\0', sizeof(Globals));
@@ -4748,7 +4848,8 @@ static void init_globals(bool first_time_only)
        Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
        Globals.ldap_delete_dn = False;
        Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
-       Globals.ldap_timeout = LDAP_CONNECT_DEFAULT_TIMEOUT;
+       Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
+       Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
        Globals.ldap_page_size = LDAP_PAGE_SIZE;
 
        Globals.ldap_debug_level = 0;
@@ -4758,6 +4859,7 @@ static void init_globals(bool first_time_only)
         * to never expire, though, when this runs out the afs client will 
         * forget the token. Set to 0 to get NEVERDATE.*/
        Globals.iAfsTokenLifetime = 604800;
+       Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
 
 /* these parameters are set to defaults that are more appropriate
    for the increasing samba install base:
@@ -4780,12 +4882,16 @@ static void init_globals(bool first_time_only)
        Globals.bWINSsupport = False;
        Globals.bWINSproxy = False;
 
+       TALLOC_FREE(Globals.szInitLogonDelayedHosts);
+       Globals.InitLogonDelay = 100; /* 100 ms default delay */
+
        Globals.bDNSproxy = True;
 
        /* this just means to use them if they exist */
        Globals.bKernelOplocks = True;
 
        Globals.bAllowTrustedDomains = True;
+       string_set(&Globals.szIdmapBackend, "tdb");
 
        string_set(&Globals.szTemplateShell, "/bin/false");
        string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
@@ -4799,17 +4905,18 @@ static void init_globals(bool first_time_only)
        Globals.clustering = False;
 
        Globals.winbind_cache_time = 300;       /* 5 minutes */
+       Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
        Globals.bWinbindEnumUsers = False;
        Globals.bWinbindEnumGroups = False;
        Globals.bWinbindUseDefaultDomain = False;
        Globals.bWinbindTrustedDomainsOnly = False;
        Globals.bWinbindNestedGroups = True;
        Globals.winbind_expand_groups = 1;
-       Globals.szWinbindNssInfo = str_list_make(NULL, "template", NULL);
+       Globals.szWinbindNssInfo = str_list_make_v3(talloc_autofree_context(), "template", NULL);
        Globals.bWinbindRefreshTickets = False;
        Globals.bWinbindOfflineLogon = False;
 
-       Globals.iIdmapCacheTime = 900; /* 15 minutes by default */
+       Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
        Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
 
        Globals.bPassdbExpandExplicit = False;
@@ -4969,7 +5076,6 @@ FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
-FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
@@ -5052,8 +5158,7 @@ FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
 FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
 FN_GLOBAL_BOOL(lp_winbind_rpc_only, &Globals.bWinbindRpcOnly)
 
-FN_GLOBAL_LIST(lp_idmap_domains, &Globals.szIdmapDomains)
-FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) /* deprecated */
+FN_GLOBAL_CONST_STRING(lp_idmap_backend, &Globals.szIdmapBackend)
 FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
 FN_GLOBAL_INTEGER(lp_idmap_cache_time, &Globals.iIdmapCacheTime)
 FN_GLOBAL_INTEGER(lp_idmap_negative_cache_time, &Globals.iIdmapNegativeCacheTime)
@@ -5067,6 +5172,7 @@ FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
 FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
+FN_GLOBAL_INTEGER(lp_ldap_connection_timeout, &Globals.ldap_connection_timeout)
 FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
 FN_GLOBAL_INTEGER(lp_ldap_debug_level, &Globals.ldap_debug_level)
 FN_GLOBAL_INTEGER(lp_ldap_debug_threshold, &Globals.ldap_debug_threshold)
@@ -5091,6 +5197,8 @@ FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
+FN_GLOBAL_LIST(lp_init_logon_delayed_hosts, &Globals.szInitLogonDelayedHosts)
+FN_GLOBAL_INTEGER(lp_init_logon_delay, &Globals.InitLogonDelay)
 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
@@ -5174,7 +5282,7 @@ FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
 FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
 FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
 FN_GLOBAL_CONST_STRING(lp_socket_options, &Globals.szSocketOptions)
-FN_GLOBAL_INTEGER(lp_config_backend, &Globals.ConfigBackend);
+FN_GLOBAL_INTEGER(lp_config_backend, &Globals.ConfigBackend)
 
 FN_LOCAL_STRING(lp_preexec, szPreExec)
 FN_LOCAL_STRING(lp_postexec, szPostExec)
@@ -5192,9 +5300,10 @@ FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
 FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
+FN_GLOBAL_INTEGER(lp_cups_connection_timeout, &Globals.cups_connection_timeout)
 FN_GLOBAL_CONST_STRING(lp_ctdbd_socket, &Globals.ctdbdSocket)
 FN_GLOBAL_LIST(lp_cluster_addresses, &Globals.szClusterAddresses)
-FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering);
+FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering)
 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
@@ -5235,6 +5344,7 @@ FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
+FN_LOCAL_BOOL(lp_access_based_share_enum, bAccessBasedShareEnum)
 FN_LOCAL_BOOL(lp_readonly, bRead_only)
 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
@@ -5309,6 +5419,7 @@ FN_LOCAL_INTEGER(lp_directory_name_cache_size, iDirectoryNameCacheSize)
 FN_LOCAL_INTEGER(lp_smb_encrypt, ismb_encrypt)
 FN_LOCAL_CHAR(lp_magicchar, magic_char)
 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
+FN_GLOBAL_INTEGER(lp_winbind_reconnect_delay, &Globals.winbind_reconnect_delay)
 FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
@@ -5320,30 +5431,34 @@ FN_GLOBAL_INTEGER(lp_client_ldap_sasl_wrapping, &Globals.client_ldap_sasl_wrappi
 
 static int map_parameter(const char *pszParmName);
 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
-static bool set_boolean(bool *pb, const char *pszParmValue);
 static const char *get_boolean(bool bool_value);
 static int getservicebyname(const char *pszServiceName,
                            struct service *pserviceDest);
 static void copy_service(struct service *pserviceDest,
                         struct service *pserviceSource,
                         struct bitmap *pcopymapDest);
-static bool do_parameter(const char *pszParmName, const char *pszParmValue);
-static bool do_section(const char *pszSectionName);
+static bool do_parameter(const char *pszParmName, const char *pszParmValue,
+                        void *userdata);
+static bool do_section(const char *pszSectionName, void *userdata);
 static void init_copymap(struct service *pservice);
 static bool hash_a_service(const char *name, int number);
 static void free_service_byindex(int iService);
+static void free_param_opts(struct param_opt_struct **popts);
 static char * canonicalize_servicename(const char *name);
 static void show_parameter(int parmIndex);
 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
 
-/* This is a helper function for parametrical options support. */
-/* It returns a pointer to parametrical option value if it exists or NULL otherwise */
-/* Actual parametrical functions are quite simple */
-static param_opt_struct *get_parametrics(int snum, const char *type, const char *option)
+/*
+ * This is a helper function for parametrical options support.  It returns a
+ * pointer to parametrical option value if it exists or NULL otherwise. Actual
+ * parametrical functions are quite simple
+ */
+static struct param_opt_struct *get_parametrics(int snum, const char *type,
+                                               const char *option)
 {
        bool global_section = False;
        char* param_key;
-        param_opt_struct *data;
+        struct param_opt_struct *data;
        
        if (snum >= iNumServices) return NULL;
        
@@ -5360,7 +5475,7 @@ static param_opt_struct *get_parametrics(int snum, const char *type, const char
        }
 
        while (data) {
-               if (strcmp(data->key, param_key) == 0) {
+               if (strwicmp(data->key, param_key) == 0) {
                        string_free(&param_key);
                        return data;
                }
@@ -5372,7 +5487,7 @@ static param_opt_struct *get_parametrics(int snum, const char *type, const char
                /* but only if we are not already working with Globals */
                data = Globals.param_opt;
                while (data) {
-                       if (strcmp(data->key, param_key) == 0) {
+                       if (strwicmp(data->key, param_key) == 0) {
                                string_free(&param_key);
                                return data;
                        }
@@ -5429,7 +5544,7 @@ static bool lp_bool(const char *s)
                return False;
        }
        
-       if (!set_boolean(&ret,s)) {
+       if (!set_boolean(s, &ret)) {
                DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
                return False;
        }
@@ -5477,7 +5592,7 @@ static int lp_enum(const char *s,const struct enum_list *_enum)
 /* the returned value is talloced on the talloc_tos() */
 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
 {
-       param_opt_struct *data = get_parametrics(snum, type, option);
+       struct param_opt_struct *data = get_parametrics(snum, type, option);
        
        if (data == NULL||data->value==NULL) {
                if (def) {
@@ -5494,7 +5609,7 @@ char *lp_parm_talloc_string(int snum, const char *type, const char *option, cons
 /* Parametric option has following syntax: 'Type: option = value' */
 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
 {
-       param_opt_struct *data = get_parametrics(snum, type, option);
+       struct param_opt_struct *data = get_parametrics(snum, type, option);
        
        if (data == NULL||data->value==NULL)
                return def;
@@ -5507,13 +5622,13 @@ const char *lp_parm_const_string(int snum, const char *type, const char *option,
 
 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
 {
-       param_opt_struct *data = get_parametrics(snum, type, option);
+       struct param_opt_struct *data = get_parametrics(snum, type, option);
 
        if (data == NULL||data->value==NULL)
                return (const char **)def;
                
        if (data->list==NULL) {
-               data->list = str_list_make(NULL, data->value, NULL);
+               data->list = str_list_make_v3(talloc_autofree_context(), data->value, NULL);
        }
 
        return (const char **)data->list;
@@ -5524,7 +5639,7 @@ const char **lp_parm_string_list(int snum, const char *type, const char *option,
 
 int lp_parm_int(int snum, const char *type, const char *option, int def)
 {
-       param_opt_struct *data = get_parametrics(snum, type, option);
+       struct param_opt_struct *data = get_parametrics(snum, type, option);
        
        if (data && data->value && *data->value)
                return lp_int(data->value);
@@ -5537,7 +5652,7 @@ int lp_parm_int(int snum, const char *type, const char *option, int def)
 
 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
 {
-       param_opt_struct *data = get_parametrics(snum, type, option);
+       struct param_opt_struct *data = get_parametrics(snum, type, option);
        
        if (data && data->value && *data->value)
                return lp_ulong(data->value);
@@ -5550,7 +5665,7 @@ unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsi
 
 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
 {
-       param_opt_struct *data = get_parametrics(snum, type, option);
+       struct param_opt_struct *data = get_parametrics(snum, type, option);
        
        if (data && data->value && *data->value)
                return lp_bool(data->value);
@@ -5564,7 +5679,7 @@ bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
 int lp_parm_enum(int snum, const char *type, const char *option,
                 const struct enum_list *_enum, int def)
 {
-       param_opt_struct *data = get_parametrics(snum, type, option);
+       struct param_opt_struct *data = get_parametrics(snum, type, option);
        
        if (data && data->value && *data->value && _enum)
                return lp_enum(data->value, _enum);
@@ -5583,14 +5698,42 @@ static void init_service(struct service *pservice)
        copy_service(pservice, &sDefault, NULL);
 }
 
+
+/**
+ * free a param_opts structure.
+ * param_opts handling should be moved to talloc;
+ * then this whole functions reduces to a TALLOC_FREE().
+ */
+
+static void free_param_opts(struct param_opt_struct **popts)
+{
+       struct param_opt_struct *opt, *next_opt;
+
+       if (popts == NULL) {
+               return;
+       }
+
+       if (*popts != NULL) {
+               DEBUG(5, ("Freeing parametrics:\n"));
+       }
+       opt = *popts;
+       while (opt != NULL) {
+               string_free(&opt->key);
+               string_free(&opt->value);
+               TALLOC_FREE(opt->list);
+               next_opt = opt->next;
+               SAFE_FREE(opt);
+               opt = next_opt;
+       }
+       *popts = NULL;
+}
+
 /***************************************************************************
  Free the dynamically allocated parts of a service struct.
 ***************************************************************************/
 
 static void free_service(struct service *pservice)
 {
-       int i;
-        param_opt_struct *data, *pdata;
        if (!pservice)
                return;
 
@@ -5598,36 +5741,12 @@ static void free_service(struct service *pservice)
                DEBUG(5, ("free_service: Freeing service %s\n",
                       pservice->szService));
 
+       free_parameters(getservicebyname(pservice->szService, NULL));
+
        string_free(&pservice->szService);
        bitmap_free(pservice->copymap);
 
-       for (i = 0; parm_table[i].label; i++) {
-               if ((parm_table[i].type == P_STRING ||
-                    parm_table[i].type == P_USTRING) &&
-                   parm_table[i].p_class == P_LOCAL)
-                       string_free((char **)
-                                   (((char *)pservice) +
-                                    PTR_DIFF(parm_table[i].ptr, &sDefault)));
-               else if (parm_table[i].type == P_LIST &&
-                        parm_table[i].p_class == P_LOCAL)
-                            TALLOC_FREE(*((char ***)
-                                          (((char *)pservice) +
-                                           PTR_DIFF(parm_table[i].ptr,
-                                                    &sDefault))));
-       }
-
-       data = pservice->param_opt;
-       if (data)
-               DEBUG(5,("Freeing parametrics:\n"));
-       while (data) {
-               DEBUG(5,("[%s = %s]\n", data->key, data->value));
-               string_free(&data->key);
-               string_free(&data->value);
-               TALLOC_FREE(data->list);
-               pdata = data->next;
-               SAFE_FREE(data);
-               data = pdata;
-       }
+       free_param_opts(&pservice->param_opt);
 
        ZERO_STRUCTP(pservice);
 }
@@ -5669,7 +5788,6 @@ static int add_a_service(const struct service *pservice, const char *name)
        int i;
        struct service tservice;
        int num_to_alloc = iNumServices + 1;
-       param_opt_struct *data, *pdata;
 
        tservice = *pservice;
 
@@ -5679,16 +5797,7 @@ static int add_a_service(const struct service *pservice, const char *name)
                if (i >= 0) {
                        /* Clean all parametric options for service */
                        /* They will be added during parsing again */
-                       data = ServicePtrs[i]->param_opt;
-                       while (data) {
-                               string_free(&data->key);
-                               string_free(&data->value);
-                               TALLOC_FREE(data->list);
-                               pdata = data->next;
-                               SAFE_FREE(data);
-                               data = pdata;
-                       }
-                       ServicePtrs[i]->param_opt = NULL;
+                       free_param_opts(&ServicePtrs[i]->param_opt);
                        return (i);
                }
        }
@@ -5830,6 +5939,7 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
        /* set the browseable flag from the global default */
 
        ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
+       ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
 
        ServicePtrs[i]->autoloaded = True;
 
@@ -6054,7 +6164,7 @@ static int map_parameter(const char *pszParmName)
 {
        int iIndex;
 
-       if (*pszParmName == '-')
+       if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
                return (-1);
 
        for (iIndex = 0; parm_table[iIndex].label; iIndex++)
@@ -6063,7 +6173,7 @@ static int map_parameter(const char *pszParmName)
 
        /* Warn only if it isn't parametric option */
        if (strchr(pszParmName, ':') == NULL)
-               DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
+               DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
        /* We do return 'fail' for parametric options as well because they are
           stored in different storage
         */
@@ -6217,49 +6327,13 @@ void show_parameter_list(void)
        }
 }
 
-/***************************************************************************
- Set a boolean variable from the text value stored in the passed string.
- Returns True in success, False if the passed string does not correctly 
- represent a boolean.
-***************************************************************************/
-
-static bool set_boolean(bool *pb, const char *pszParmValue)
-{
-       bool bRetval;
-       bool value;
-
-       bRetval = True;
-       value = False;
-       if (strwicmp(pszParmValue, "yes") == 0 ||
-           strwicmp(pszParmValue, "true") == 0 ||
-           strwicmp(pszParmValue, "1") == 0)
-               value = True;
-       else if (strwicmp(pszParmValue, "no") == 0 ||
-                   strwicmp(pszParmValue, "False") == 0 ||
-                   strwicmp(pszParmValue, "0") == 0)
-               value = False;
-       else {
-               DEBUG(2,
-                     ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
-                      pszParmValue));
-               bRetval = False;
-       }
-
-       if ((pb != NULL) && (bRetval != False)) {
-               *pb = value;
-       }
-
-       return (bRetval);
-}
-
-
 /***************************************************************************
  Check if a given string correctly represents a boolean value.
 ***************************************************************************/
 
 bool lp_string_is_valid_boolean(const char *parm_value)
 {
-       return set_boolean(NULL, parm_value);
+       return set_boolean(parm_value, NULL);
 }
 
 /***************************************************************************
@@ -6284,7 +6358,7 @@ bool lp_invert_boolean(const char *str, const char **inverse_str)
 {
        bool val;
 
-       if (!set_boolean(&val, str)) {
+       if (!set_boolean(str, &val)) {
                return False;
        }
 
@@ -6302,7 +6376,7 @@ bool lp_canonicalize_boolean(const char *str, const char**canon_str)
 {
        bool val;
 
-       if (!set_boolean(&val, str)) {
+       if (!set_boolean(str, &val)) {
                return False;
        }
 
@@ -6347,13 +6421,51 @@ static int getservicebyname(const char *pszServiceName, struct service *pservice
  If pcopymapDest is NULL then copy all fields
 ***************************************************************************/
 
+/**
+ * Add a parametric option to a param_opt_struct,
+ * replacing old value, if already present.
+ */
+static void set_param_opt(struct param_opt_struct **opt_list,
+                         const char *opt_name,
+                         const char *opt_value)
+{
+       struct param_opt_struct *new_opt, *opt;
+       bool not_added;
+
+       if (opt_list == NULL) {
+               return;
+       }
+
+       opt = *opt_list;
+       not_added = true;
+
+       /* Traverse destination */
+       while (opt) {
+               /* If we already have same option, override it */
+               if (strwicmp(opt->key, opt_name) == 0) {
+                       string_free(&opt->value);
+                       TALLOC_FREE(opt->list);
+                       opt->value = SMB_STRDUP(opt_value);
+                       not_added = false;
+                       break;
+               }
+               opt = opt->next;
+       }
+       if (not_added) {
+           new_opt = SMB_XMALLOC_P(struct param_opt_struct);
+           new_opt->key = SMB_STRDUP(opt_name);
+           new_opt->value = SMB_STRDUP(opt_value);
+           new_opt->list = NULL;
+           DLIST_ADD(*opt_list, new_opt);
+       }
+}
+
 static void copy_service(struct service *pserviceDest, struct service *pserviceSource,
                         struct bitmap *pcopymapDest)
 {
        int i;
        bool bcopyall = (pcopymapDest == NULL);
-       param_opt_struct *data, *pdata, *paramo;
-       bool not_added;
+       struct param_opt_struct *data;
 
        for (i = 0; parm_table[i].label; i++)
                if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
@@ -6394,7 +6506,7 @@ static void copy_service(struct service *pserviceDest, struct service *pserviceS
                                        break;
                                case P_LIST:
                                        TALLOC_FREE(*((char ***)dest_ptr));
-                                       str_list_copy(NULL, (char ***)dest_ptr,
+                                       *((char ***)dest_ptr) = str_list_copy(NULL, 
                                                      *(const char ***)src_ptr);
                                        break;
                                default:
@@ -6411,27 +6523,7 @@ static void copy_service(struct service *pserviceDest, struct service *pserviceS
        
        data = pserviceSource->param_opt;
        while (data) {
-               not_added = True;
-               pdata = pserviceDest->param_opt;
-               /* Traverse destination */
-               while (pdata) {
-                       /* If we already have same option, override it */
-                       if (strcmp(pdata->key, data->key) == 0) {
-                               string_free(&pdata->value);
-                               TALLOC_FREE(data->list);
-                               pdata->value = SMB_STRDUP(data->value);
-                               not_added = False;
-                               break;
-                       }
-                       pdata = pdata->next;
-               }
-               if (not_added) {
-                   paramo = SMB_XMALLOC_P(param_opt_struct);
-                   paramo->key = SMB_STRDUP(data->key);
-                   paramo->value = SMB_STRDUP(data->value);
-                   paramo->list = NULL;
-                   DLIST_ADD(pserviceDest->param_opt, paramo);
-               }
+               set_param_opt(&pserviceDest->param_opt, data->key, data->value);
                data = data->next;
        }
 }
@@ -6482,25 +6574,65 @@ bool service_ok(int iService)
        return (bRetval);
 }
 
+static struct smbconf_ctx *lp_smbconf_ctx(void)
+{
+       WERROR werr;
+       static struct smbconf_ctx *conf_ctx = NULL;
+
+       if (conf_ctx == NULL) {
+               werr = smbconf_init(NULL, &conf_ctx, "registry:");
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG(1, ("error initializing registry configuration: "
+                                 "%s\n", win_errstr(werr)));
+                       conf_ctx = NULL;
+               }
+       }
+
+       return conf_ctx;
+}
+
+static bool process_smbconf_service(struct smbconf_service *service)
+{
+       uint32_t count;
+       bool ret;
+
+       if (service == NULL) {
+               return false;
+       }
+
+       ret = do_section(service->name, NULL);
+       if (ret != true) {
+               return false;
+       }
+       for (count = 0; count < service->num_params; count++) {
+               ret = do_parameter(service->param_names[count],
+                                  service->param_values[count],
+                                  NULL);
+               if (ret != true) {
+                       return false;
+               }
+       }
+       return true;
+}
+
 /*
  * process_registry_globals
  */
-static bool process_registry_globals(bool (*pfunc)(const char *, const char *))
+static bool process_registry_globals(void)
 {
        WERROR werr;
-       char **param_names;
-       char **param_values;
-       uint32_t num_params;
-       uint32_t count;
+       struct smbconf_service *service = NULL;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
+       struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
        bool ret = false;
 
        if (conf_ctx == NULL) {
-               /* first time */
-               werr = smbconf_init_reg(NULL, &conf_ctx, NULL);
-               if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
-               }
+               goto done;
+       }
+
+       ret = do_parameter("registry shares", "yes", NULL);
+       if (!ret) {
+               goto done;
        }
 
        if (!smbconf_share_exists(conf_ctx, GLOBAL_NAME)) {
@@ -6510,20 +6642,55 @@ static bool process_registry_globals(bool (*pfunc)(const char *, const char *))
                goto done;
        }
 
-       werr = smbconf_get_share(conf_ctx, mem_ctx, GLOBAL_NAME,
-                                &num_params, &param_names, &param_values);
+       werr = smbconf_get_share(conf_ctx, mem_ctx, GLOBAL_NAME, &service);
        if (!W_ERROR_IS_OK(werr)) {
                goto done;
        }
 
-       for (count = 0; count < num_params; count++) {
-               ret = pfunc(param_names[count], param_values[count]);
-               if (ret != true) {
+       ret = process_smbconf_service(service);
+       if (!ret) {
+               goto done;
+       }
+
+       /* store the csn */
+       smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
+
+done:
+       TALLOC_FREE(mem_ctx);
+       return ret;
+}
+
+static bool process_registry_shares(void)
+{
+       WERROR werr;
+       uint32_t count;
+       struct smbconf_service **service = NULL;
+       uint32_t num_shares = 0;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+       struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
+       bool ret = false;
+
+       if (conf_ctx == NULL) {
+               goto done;
+       }
+
+       werr = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
+       if (!W_ERROR_IS_OK(werr)) {
+               goto done;
+       }
+
+       ret = true;
+
+       for (count = 0; count < num_shares; count++) {
+               if (strequal(service[count]->name, GLOBAL_NAME)) {
+                       continue;
+               }
+               ret = process_smbconf_service(service[count]);
+               if (!ret) {
                        goto done;
                }
        }
 
-       ret = pfunc("registry shares", "yes");
        /* store the csn */
        smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
 
@@ -6605,14 +6772,10 @@ bool lp_file_list_changed(void)
        DEBUG(6, ("lp_file_list_changed()\n"));
 
        if (lp_config_backend_is_registry()) {
+               struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
+
                if (conf_ctx == NULL) {
-                       WERROR werr;
-                       werr = smbconf_init_reg(NULL, &conf_ctx, NULL);
-                       if (!W_ERROR_IS_OK(werr)) {
-                               DEBUG(0, ("error opening configuration: %s\n",
-                                         dos_errstr(werr)));
-                               return false;
-                       }
+                       return false;
                }
                if (smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL)) {
                        DEBUGADD(6, ("registry config changed\n"));
@@ -6710,18 +6873,32 @@ static bool handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
 static bool handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
 {
        TALLOC_FREE(Globals.szNetbiosAliases);
-       Globals.szNetbiosAliases = str_list_make(NULL, pszParmValue, NULL);
+       Globals.szNetbiosAliases = str_list_make_v3(talloc_autofree_context(), pszParmValue, NULL);
        return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
 }
 
 /***************************************************************************
  Handle the include operation.
 ***************************************************************************/
+static bool bAllowIncludeRegistry = true;
 
 static bool handle_include(int snum, const char *pszParmValue, char **ptr)
 {
        char *fname;
 
+       if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
+               if (!bAllowIncludeRegistry) {
+                       return true;
+               }
+               if (bInGlobalSection) {
+                       return process_registry_globals();
+               } else {
+                       DEBUG(1, ("\"include = registry\" only effective "
+                                 "in %s section\n", GLOBAL_NAME));
+                       return false;
+               }
+       }
+
        fname = alloc_sub_basic(get_current_username(),
                                current_user_info.domain,
                                pszParmValue);
@@ -6730,15 +6907,15 @@ static bool handle_include(int snum, const char *pszParmValue, char **ptr)
 
        string_set(ptr, fname);
 
-       if (file_exist(fname, NULL)) {
-               bool ret = pm_process(fname, do_section, do_parameter);
+       if (file_exist(fname)) {
+               bool ret = pm_process(fname, do_section, do_parameter, NULL);
                SAFE_FREE(fname);
                return ret;
        }
 
        DEBUG(2, ("Can't find include file %s\n", fname));
        SAFE_FREE(fname);
-       return false;
+       return true;
 }
 
 /***************************************************************************
@@ -6940,9 +7117,11 @@ static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue
        for (i = 0; parm->enum_list[i].name; i++) {
                if ( strequal(pszParmValue, parm->enum_list[i].name)) {
                        *ptr = parm->enum_list[i].value;
-                       break;
+                       return;
                }
        }
+       DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
+                 pszParmValue, parm->label));
 }
 
 /***************************************************************************
@@ -6989,14 +7168,24 @@ static void init_copymap(struct service *pservice)
                        bitmap_set(pservice->copymap, i);
 }
 
+/***************************************************************************
+ Return the local pointer to a parameter given a service struct and the
+ pointer into the default structure.
+***************************************************************************/
+
+static void *lp_local_ptr(struct service *service, void *ptr)
+{
+       return (void *)(((char *)service) + PTR_DIFF(ptr, &sDefault));
+}
+
 /***************************************************************************
  Return the local pointer to a parameter given the service number and the 
  pointer into the default structure.
 ***************************************************************************/
 
-void *lp_local_ptr(int snum, void *ptr)
+void *lp_local_ptr_by_snum(int snum, void *ptr)
 {
-       return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
+       return lp_local_ptr(ServicePtrs[snum], ptr);
 }
 
 /***************************************************************************
@@ -7006,65 +7195,28 @@ void *lp_local_ptr(int snum, void *ptr)
 
 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
 {
-       int parmnum, i, slen;
+       int parmnum, i;
        void *parm_ptr = NULL;  /* where we are going to store the result */
        void *def_ptr = NULL;
-       char *param_key = NULL;
-       char *sep;
-       param_opt_struct *paramo, *data;
-       bool not_added;
+       struct param_opt_struct **opt_list;
 
        parmnum = map_parameter(pszParmName);
 
        if (parmnum < 0) {
-               if ((sep=strchr(pszParmName, ':')) != NULL) {
-                       TALLOC_CTX *frame = talloc_stackframe();
-
-                       *sep = '\0';
-                       param_key = talloc_asprintf(frame, "%s:", pszParmName);
-                       if (!param_key) {
-                               TALLOC_FREE(frame);
-                               return false;
-                       }
-                       slen = strlen(param_key);
-                       param_key = talloc_asprintf_append(param_key, sep+1);
-                       if (!param_key) {
-                               TALLOC_FREE(frame);
-                               return false;
-                       }
-                       trim_char(param_key+slen, ' ', ' ');
-                       not_added = True;
-                       data = (snum < 0) ? Globals.param_opt :
-                               ServicePtrs[snum]->param_opt;
-                       /* Traverse destination */
-                       while (data) {
-                               /* If we already have same option, override it */
-                               if (strcmp(data->key, param_key) == 0) {
-                                       string_free(&data->value);
-                                       TALLOC_FREE(data->list);
-                                       data->value = SMB_STRDUP(pszParmValue);
-                                       not_added = False;
-                                       break;
-                               }
-                               data = data->next;
-                       }
-                       if (not_added) {
-                               paramo = SMB_XMALLOC_P(param_opt_struct);
-                               paramo->key = SMB_STRDUP(param_key);
-                               paramo->value = SMB_STRDUP(pszParmValue);
-                               paramo->list = NULL;
-                               if (snum < 0) {
-                                       DLIST_ADD(Globals.param_opt, paramo);
-                               } else {
-                                       DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
-                               }
-                       }
-
-                       *sep = ':';
-                       TALLOC_FREE(frame);
+               if (strchr(pszParmName, ':') == NULL) {
+                       DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
+                                 pszParmName));
                        return (True);
                }
-               DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
+
+               /*
+                * We've got a parametric option
+                */
+
+               opt_list = (snum < 0)
+                       ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
+               set_param_opt(opt_list, pszParmName, pszParmValue);
+
                return (True);
        }
 
@@ -7085,9 +7237,7 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                               pszParmName));
                        return (True);
                }
-               parm_ptr =
-                       ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
-                                                           &sDefault);
+               parm_ptr = lp_local_ptr_by_snum(snum, def_ptr);
        }
 
        if (snum >= 0) {
@@ -7103,8 +7253,8 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
 
        /* if it is a special case then go ahead */
        if (parm_table[parmnum].special) {
-               parm_table[parmnum].special(snum, pszParmValue, (char **)parm_ptr);
-               return (True);
+               return parm_table[parmnum].special(snum, pszParmValue,
+                                                  (char **)parm_ptr);
        }
 
        /* now switch on the type of variable it is */
@@ -7135,8 +7285,8 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
 
                case P_LIST:
                        TALLOC_FREE(*((char ***)parm_ptr));
-                       *(char ***)parm_ptr = str_list_make(
-                               NULL, pszParmValue, NULL);
+                       *(char ***)parm_ptr = str_list_make_v3(
+                               talloc_autofree_context(), pszParmValue, NULL);
                        break;
 
                case P_STRING:
@@ -7162,7 +7312,8 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
  Process a parameter.
 ***************************************************************************/
 
-static bool do_parameter(const char *pszParmName, const char *pszParmValue)
+static bool do_parameter(const char *pszParmName, const char *pszParmValue,
+                        void *userdata)
 {
        if (!bInGlobalSection && bGlobalOnly)
                return (True);
@@ -7259,7 +7410,7 @@ static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
                        return (*((char *)ptr1) == *((char *)ptr2));
 
                case P_LIST:
-                       return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
+                       return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
 
                case P_STRING:
                case P_USTRING:
@@ -7292,7 +7443,7 @@ void init_locals(void)
  Returns True on success, False on failure. 
 ***************************************************************************/
 
-static bool do_section(const char *pszSectionName)
+static bool do_section(const char *pszSectionName, void *userdata)
 {
        bool bRetval;
        bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
@@ -7348,8 +7499,8 @@ static bool is_default(int i)
                return False;
        switch (parm_table[i].type) {
                case P_LIST:
-                       return str_list_compare (parm_table[i].def.lvalue, 
-                                               *(char ***)parm_table[i].ptr);
+                       return str_list_equal((const char **)parm_table[i].def.lvalue, 
+                                               *(const char ***)parm_table[i].ptr);
                case P_STRING:
                case P_USTRING:
                        return strequal(parm_table[i].def.svalue,
@@ -7379,7 +7530,7 @@ Display the contents of the global structure.
 static void dump_globals(FILE *f)
 {
        int i;
-       param_opt_struct *data;
+       struct param_opt_struct *data;
        
        fprintf(f, "[global]\n");
 
@@ -7423,7 +7574,7 @@ bool lp_is_default(int snum, struct parm_struct *parm)
 static void dump_a_service(struct service *pService, FILE * f)
 {
        int i;
-       param_opt_struct *data;
+       struct param_opt_struct *data;
        
        if (pService != &sDefault)
                fprintf(f, "[%s]\n", pService->szService);
@@ -7684,7 +7835,7 @@ static void lp_add_auto_services(char *str)
  Auto-load one printer.
 ***************************************************************************/
 
-void lp_add_one_printer(char *name, char *comment)
+void lp_add_one_printer(const char *name, const char *comment, void *pdata)
 {
        int printers = lp_servicenumber(PRINTERS_NAME);
        int i;
@@ -7763,9 +7914,8 @@ static void lp_save_defaults(void)
                        continue;
                switch (parm_table[i].type) {
                        case P_LIST:
-                               str_list_copy(
-                                       NULL, &(parm_table[i].def.lvalue),
-                                       *(const char ***)parm_table[i].ptr);
+                               parm_table[i].def.lvalue = str_list_copy(
+                                       NULL, *(const char ***)parm_table[i].ptr);
                                break;
                        case P_STRING:
                        case P_USTRING:
@@ -8222,7 +8372,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
                return -1;
        }
 
-       lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
+       lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
 
        close(fd);
        if (lines == NULL) {
@@ -8237,7 +8387,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
        /* Should we allow printers to be shared... ? */
        ctx = talloc_init("usershare_sd_xctx");
        if (!ctx) {
-               file_lines_free(lines);
+               TALLOC_FREE(lines);
                return 1;
        }
 
@@ -8245,11 +8395,11 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
                        iService, lines, numlines, &sharepath,
                        &comment, &psd, &guest_ok) != USERSHARE_OK) {
                talloc_destroy(ctx);
-               file_lines_free(lines);
+               TALLOC_FREE(lines);
                return -1;
        }
 
-       file_lines_free(lines);
+       TALLOC_FREE(lines);
 
        /* Everything ok - add the service possibly using a template. */
        if (iService < 0) {
@@ -8576,6 +8726,7 @@ void gfree_loadparm(void)
                SAFE_FREE( f );
                f = next;
        }
+       file_lists = NULL;
 
        /* Free resources allocated to services */
 
@@ -8591,17 +8742,7 @@ void gfree_loadparm(void)
        /* Now release all resources allocated to global
           parameters and the default service */
 
-       for (i = 0; parm_table[i].label; i++) 
-       {
-               if ( parm_table[i].type == P_STRING 
-                       || parm_table[i].type == P_USTRING ) 
-               {
-                       string_free( (char**)parm_table[i].ptr );
-               }
-               else if (parm_table[i].type == P_LIST) {
-                       TALLOC_FREE( *((char***)parm_table[i].ptr) );
-               }
-       }
+       free_global_parameters();
 }
 
 
@@ -8622,30 +8763,29 @@ bool lp_is_in_client(void)
     return in_client;
 }
 
-
-
-
 /***************************************************************************
  Load the services array from the services file. Return True on success, 
  False on failure.
 ***************************************************************************/
 
-bool lp_load(const char *pszFname,
-             bool global_only,
-             bool save_defaults,
-            bool add_ipc,
-             bool initialize_globals)
+bool lp_load_ex(const char *pszFname,
+               bool global_only,
+               bool save_defaults,
+               bool add_ipc,
+               bool initialize_globals,
+               bool allow_include_registry,
+               bool allow_registry_shares)
 {
        char *n2 = NULL;
        bool bRetval;
-       param_opt_struct *data, *pdata;
 
        bRetval = False;
 
-       DEBUG(3, ("lp_load: refreshing parameters\n"));
+       DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
 
        bInGlobalSection = True;
        bGlobalOnly = global_only;
+       bAllowIncludeRegistry = allow_include_registry;
 
        init_globals(! initialize_globals);
        debug_init();
@@ -8655,32 +8795,22 @@ bool lp_load(const char *pszFname,
                lp_save_defaults();
        }
 
-       if (Globals.param_opt != NULL) {
-               data = Globals.param_opt;
-               while (data) {
-                       string_free(&data->key);
-                       string_free(&data->value);
-                       TALLOC_FREE(data->list);
-                       pdata = data->next;
-                       SAFE_FREE(data);
-                       data = pdata;
-               }
-               Globals.param_opt = NULL;
-       }
+       free_param_opts(&Globals.param_opt);
+
+       /* We get sections first, so have to start 'behind' to make up */
+       iServiceIndex = -1;
 
        if (lp_config_backend_is_file()) {
                n2 = alloc_sub_basic(get_current_username(),
                                        current_user_info.domain,
                                        pszFname);
                if (!n2) {
-                       smb_panic("lp_load: out of memory");
+                       smb_panic("lp_load_ex: out of memory");
                }
 
                add_to_file_list(pszFname, n2);
 
-               /* We get sections first, so have to start 'behind' to make up */
-               iServiceIndex = -1;
-               bRetval = pm_process(n2, do_section, do_parameter);
+               bRetval = pm_process(n2, do_section, do_parameter, NULL);
                SAFE_FREE(n2);
 
                /* finish up the last section */
@@ -8701,21 +8831,27 @@ bool lp_load(const char *pszFname,
                         */
                        config_backend = CONFIG_BACKEND_REGISTRY;
                        /* start over */
-                       DEBUG(1, ("lp_load: changing to config backend "
+                       DEBUG(1, ("lp_load_ex: changing to config backend "
                                  "registry\n"));
                        init_globals(false);
                        lp_kill_all_services();
-                       return lp_load(pszFname, global_only, save_defaults,
-                                      add_ipc, initialize_globals);
+                       return lp_load_ex(pszFname, global_only, save_defaults,
+                                         add_ipc, initialize_globals,
+                                         allow_include_registry,
+                                         allow_registry_shares);
                }
        } else if (lp_config_backend_is_registry()) {
-               bRetval = process_registry_globals(do_parameter);
+               bRetval = process_registry_globals();
        } else {
                DEBUG(0, ("Illegal config  backend given: %d\n",
                          lp_config_backend()));
                bRetval = false;
        }
 
+       if (bRetval && lp_registry_shares() && allow_registry_shares) {
+               bRetval = process_registry_shares();
+       }
+
        lp_add_auto_services(lp_auto_services());
 
        if (add_ipc) {
@@ -8741,16 +8877,49 @@ bool lp_load(const char *pszFname,
 
        init_iconv();
 
+       bAllowIncludeRegistry = true;
+
        return (bRetval);
 }
 
-/***************************************************************************
- Reset the max number of services.
-***************************************************************************/
+bool lp_load(const char *pszFname,
+            bool global_only,
+            bool save_defaults,
+            bool add_ipc,
+            bool initialize_globals)
+{
+       return lp_load_ex(pszFname,
+                         global_only,
+                         save_defaults,
+                         add_ipc,
+                         initialize_globals,
+                         true, false);
+}
 
-void lp_resetnumservices(void)
+bool lp_load_initial_only(const char *pszFname)
 {
-       iNumServices = 0;
+       return lp_load_ex(pszFname,
+                         true,
+                         false,
+                         false,
+                         true,
+                         false,
+                         false);
+}
+
+bool lp_load_with_registry_shares(const char *pszFname,
+                                 bool global_only,
+                                 bool save_defaults,
+                                 bool add_ipc,
+                                 bool initialize_globals)
+{
+       return lp_load_ex(pszFname,
+                         global_only,
+                         save_defaults,
+                         add_ipc,
+                         initialize_globals,
+                         true,
+                         true);
 }
 
 /***************************************************************************
@@ -9073,7 +9242,7 @@ void lp_remove_service(int snum)
 
 void lp_copy_service(int snum, const char *new_name)
 {
-       do_section(new_name);
+       do_section(new_name, NULL);
        if (snum >= 0) {
                snum = lp_servicenumber(new_name);
                if (snum >= 0)
@@ -9323,3 +9492,18 @@ int lp_min_receive_file_size(void)
        }
        return MIN(Globals.iminreceivefile, BUFFER_SIZE);
 }
+
+/*******************************************************************
+ If socket address is an empty character string, it is necessary to 
+ define it as "0.0.0.0". 
+********************************************************************/
+
+const char *lp_socket_address(void)
+{
+       char *sock_addr = Globals.szSocketAddress;
+       
+       if (sock_addr[0] == '\0'){
+               string_set(&Globals.szSocketAddress, "0.0.0.0");
+       }
+       return  Globals.szSocketAddress;
+}