a0d4db6f57740f7f6c53929b1707cf7a510af676
[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 "registry.h"
23 #include "librpc/gen_ndr/winreg.h"
24
25 static const struct {
26         uint32_t id;
27         const char *name;
28 } reg_value_types[] = {
29         { REG_SZ, "REG_SZ" },
30         { REG_DWORD, "REG_DWORD" },
31         { REG_BINARY, "REG_BINARY" },
32         { REG_EXPAND_SZ, "REG_EXPAND_SZ" },
33         { REG_NONE, "REG_NONE" },
34         { 0, NULL }
35 };
36
37 /* Return string description of registry value type */
38 const char *str_regtype(int type)
39 {
40         int i;
41         for (i = 0; reg_value_types[i].name; i++) {
42                 if (reg_value_types[i].id == type) 
43                         return reg_value_types[i].name;
44         }
45
46         return "Unknown";
47 }
48
49 char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct registry_value *v)
50
51   char *ret = NULL;
52
53   if(v->data.length == 0) return talloc_strdup(mem_ctx, "");
54
55   switch (v->data_type) {
56   case REG_EXPAND_SZ:
57   case REG_SZ:
58       convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, v->data.data, v->data.length, (void **)&ret);
59           return ret;
60
61   case REG_BINARY:
62           ret = data_blob_hex_string(mem_ctx, &v->data);
63           return ret;
64
65   case REG_DWORD:
66           if (*(int *)v->data.data == 0)
67                   return talloc_strdup(mem_ctx, "0");
68
69           return talloc_asprintf(mem_ctx, "0x%x", *(int *)v->data.data);
70
71   case REG_MULTI_SZ:
72         /* FIXME */
73     break;
74
75   default:
76     break;
77   } 
78
79   return ret;
80 }
81
82 char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val) 
83 {
84         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));
85 }
86
87 BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, struct registry_value **value)
88 {
89         int i;
90         *value = talloc(mem_ctx, struct registry_value);
91         (*value)->data_type = -1;
92
93         /* Find the correct type */
94         for (i = 0; reg_value_types[i].name; i++) {
95                 if (!strcmp(reg_value_types[i].name, type_str)) {
96                         (*value)->data_type = reg_value_types[i].id;
97                         break;
98                 }
99         }
100
101         if ((*value)->data_type == -1) 
102                 return False;
103
104         /* Convert data appropriately */
105
106         switch ((*value)->data_type) 
107         {
108                 case REG_SZ:
109                 case REG_EXPAND_SZ:
110                 (*value)->data.length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&(*value)->data.data);
111                         break;
112
113                 case REG_DWORD: {
114                         uint32_t tmp = strtol(data_str, NULL, 0);
115                         (*value)->data = data_blob_talloc(mem_ctx, &tmp, 4);
116                         }
117                         break;
118
119                 case REG_NONE:
120                         ZERO_STRUCT((*value)->data);
121                         break;
122         
123                 default:
124                 case REG_BINARY: /* FIXME */
125                         return False;
126         }
127         return True;
128 }
129
130 /**
131  * Replace all \'s with /'s
132  */
133 char *reg_path_win2unix(char *path) 
134 {
135         int i;
136         for(i = 0; path[i]; i++) {
137                 if(path[i] == '\\') path[i] = '/';
138         }
139         return path;
140 }
141 /**
142  * Replace all /'s with \'s
143  */
144 char *reg_path_unix2win(char *path) 
145 {
146         int i;
147         for(i = 0; path[i]; i++) {
148                 if(path[i] == '/') path[i] = '\\';
149         }
150         return path;
151 }
152
153 /* Open a key by name (including the predefined key name!) */
154 WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result)
155 {
156         struct registry_key *predef;
157         WERROR error;
158         int predeflength;
159         char *predefname;
160
161         if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name;
162         else predeflength = strlen(name);
163
164         predefname = strndup(name, predeflength);
165         error = reg_get_predefined_key_by_name(handle, predefname, &predef);
166         SAFE_FREE(predefname);
167
168         if(!W_ERROR_IS_OK(error)) {
169                 return error;
170         }
171
172         if (strchr(name, '\\')) {
173                 return reg_open_key(mem_ctx, predef, strchr(name, '\\')+1, result);
174         } else {
175                 *result = predef;
176                 return WERR_OK;
177         }
178 }
179
180 static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, struct registry_key **parent, const char **name)
181 {
182         char *parent_name;
183         WERROR error;
184         
185         if (strchr(path, '\\') == NULL) {
186                 return WERR_FOOBAR;
187         }
188         
189         parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-1-path);
190
191         error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent);
192         if (!W_ERROR_IS_OK(error)) {
193                 return error;
194         }
195         
196         *name = talloc_strdup(mem_ctx, strchr(path, '\\')+1);
197
198         return WERR_OK;
199 }
200
201 WERROR reg_key_del_abs(struct registry_context *ctx, const char *path)
202 {
203         struct registry_key *parent;
204         const char *n;
205         TALLOC_CTX *mem_ctx = talloc_init("reg_key_del_abs");
206         WERROR error;
207         
208         if (!strchr(path, '\\')) {
209                 return WERR_FOOBAR;
210         }
211         
212         error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
213         if (W_ERROR_IS_OK(error)) {
214                 error = reg_key_del(parent, n);
215         }
216
217         talloc_free(mem_ctx);
218
219         return error;
220 }
221
222 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)
223 {
224         struct registry_key *parent;
225         const char *n;
226         WERROR error;
227         
228         if (!strchr(path, '\\')) {
229                 return WERR_FOOBAR;
230         }
231         
232         error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
233         if (W_ERROR_IS_OK(error)) {
234                 error = reg_key_add_name(mem_ctx, parent, n, access_mask, sec_desc, result);
235         }
236
237         return error;
238 }