r15207: Introduce PRIVATE_DEPENDENCIES and PUBLIC_DEPENDENCIES as replacement
[bbaumbach/samba-autobuild/.git] / source4 / lib / registry / common / reg_util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Transparent registry backend handling
4    Copyright (C) Jelmer Vernooij                        2003-2004.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "lib/registry/registry.h"
23 #include "librpc/gen_ndr/winreg.h"
24
25 /**
26  * @file
27  * @brief Registry utility functions
28  */
29
30 static const struct {
31         uint32_t id;
32         const char *name;
33 } reg_value_types[] = {
34         { REG_SZ, "REG_SZ" },
35         { REG_DWORD, "REG_DWORD" },
36         { REG_BINARY, "REG_BINARY" },
37         { REG_EXPAND_SZ, "REG_EXPAND_SZ" },
38         { REG_NONE, "REG_NONE" },
39         { 0, NULL }
40 };
41
42 /** Return string description of registry value type */
43 _PUBLIC_ const char *str_regtype(int type)
44 {
45         int i;
46         for (i = 0; reg_value_types[i].name; i++) {
47                 if (reg_value_types[i].id == type) 
48                         return reg_value_types[i].name;
49         }
50
51         return "Unknown";
52 }
53
54 _PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, DATA_BLOB *data)
55
56   char *ret = NULL;
57
58   if(data->length == 0) return talloc_strdup(mem_ctx, "");
59
60   switch (type) {
61   case REG_EXPAND_SZ:
62   case REG_SZ:
63       convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, data->data, data->length, (void **)&ret);
64           return ret;
65
66   case REG_BINARY:
67           ret = data_blob_hex_string(mem_ctx, data);
68           return ret;
69
70   case REG_DWORD:
71           if (*(int *)data->data == 0)
72                   return talloc_strdup(mem_ctx, "0");
73
74           return talloc_asprintf(mem_ctx, "0x%x", *(int *)data->data);
75
76   case REG_MULTI_SZ:
77         /* FIXME */
78     break;
79
80   default:
81     break;
82   } 
83
84   return ret;
85 }
86
87 /** Generate a string that describes a registry value */
88 _PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) 
89 {
90         return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"<No Name>", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val->data_type, &val->data));
91 }
92
93 _PUBLIC_ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, uint32_t *type, DATA_BLOB *data)
94 {
95         int i;
96         *type = -1;
97
98         /* Find the correct type */
99         for (i = 0; reg_value_types[i].name; i++) {
100                 if (!strcmp(reg_value_types[i].name, type_str)) {
101                         *type = reg_value_types[i].id;
102                         break;
103                 }
104         }
105
106         if (*type == -1) 
107                 return False;
108
109         /* Convert data appropriately */
110
111         switch (*type) 
112         {
113                 case REG_SZ:
114                 case REG_EXPAND_SZ:
115                 data->length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&data->data);
116                         break;
117
118                 case REG_DWORD: {
119                         uint32_t tmp = strtol(data_str, NULL, 0);
120                         *data = data_blob_talloc(mem_ctx, &tmp, 4);
121                         }
122                         break;
123
124                 case REG_NONE:
125                         ZERO_STRUCT(data);
126                         break;
127         
128                 case REG_BINARY: 
129                         *data = strhex_to_data_blob(data_str);
130                         talloc_steal(mem_ctx, data->data);
131                         break;
132                         
133                 default:
134                         /* FIXME */
135                         return False;
136         }
137         return True;
138 }
139
140 /**
141  * Replace all \'s with /'s
142  */
143 char *reg_path_win2unix(char *path) 
144 {
145         int i;
146         for(i = 0; path[i]; i++) {
147                 if(path[i] == '\\') path[i] = '/';
148         }
149         return path;
150 }
151 /**
152  * Replace all /'s with \'s
153  */
154 char *reg_path_unix2win(char *path) 
155 {
156         int i;
157         for(i = 0; path[i]; i++) {
158                 if(path[i] == '/') path[i] = '\\';
159         }
160         return path;
161 }
162
163 /** Open a key by name (including the predefined key name!) */
164 WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result)
165 {
166         struct registry_key *predef;
167         WERROR error;
168         int predeflength;
169         char *predefname;
170
171         if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name;
172         else predeflength = strlen(name);
173
174         predefname = strndup(name, predeflength);
175         error = reg_get_predefined_key_by_name(handle, predefname, &predef);
176         SAFE_FREE(predefname);
177
178         if(!W_ERROR_IS_OK(error)) {
179                 return error;
180         }
181
182         if (strchr(name, '\\')) {
183                 return reg_open_key(mem_ctx, predef, strchr(name, '\\')+1, result);
184         } else {
185                 *result = predef;
186                 return WERR_OK;
187         }
188 }
189
190 static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, struct registry_key **parent, const char **name)
191 {
192         char *parent_name;
193         WERROR error;
194         
195         if (strchr(path, '\\') == NULL) {
196                 return WERR_FOOBAR;
197         }
198         
199         parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-1-path);
200
201         error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent);
202         if (!W_ERROR_IS_OK(error)) {
203                 return error;
204         }
205         
206         *name = talloc_strdup(mem_ctx, strchr(path, '\\')+1);
207
208         return WERR_OK;
209 }
210
211 WERROR reg_key_del_abs(struct registry_context *ctx, const char *path)
212 {
213         struct registry_key *parent;
214         const char *n;
215         TALLOC_CTX *mem_ctx = talloc_init("reg_key_del_abs");
216         WERROR error;
217         
218         if (!strchr(path, '\\')) {
219                 return WERR_FOOBAR;
220         }
221         
222         error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
223         if (W_ERROR_IS_OK(error)) {
224                 error = reg_key_del(parent, n);
225         }
226
227         talloc_free(mem_ctx);
228
229         return error;
230 }
231
232 WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **result)
233 {
234         struct registry_key *parent;
235         const char *n;
236         WERROR error;
237         
238         if (!strchr(path, '\\')) {
239                 return WERR_FOOBAR;
240         }
241         
242         error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
243         if (W_ERROR_IS_OK(error)) {
244                 error = reg_key_add_name(mem_ctx, parent, n, access_mask, sec_desc, result);
245         }
246
247         return error;
248 }