r22736: Start to merge the low-hanging fruit from the now 7000-line cluster patch.
[samba.git] / source3 / lib / util_reg.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * Registry helper routines
4  * Copyright (C) Volker Lendecke 2006
5  * 
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; either version 2 of the License, or (at your option)
9  * any later version.
10  * 
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with
17  * this program; if not, write to the Free Software Foundation, Inc., 675
18  * Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "includes.h"
22
23 const char *reg_type_lookup(enum winreg_Type type)
24 {
25         const char *result;
26
27         switch(type) {
28         case REG_NONE:
29                 result = "REG_NONE";
30                 break;
31         case REG_SZ:
32                 result = "REG_SZ";
33                 break;
34         case REG_EXPAND_SZ:
35                 result = "REG_EXPAND_SZ";
36                 break;
37         case REG_BINARY:
38                 result = "REG_BINARY";
39                 break;
40         case REG_DWORD:
41                 result = "REG_DWORD";
42                 break;
43         case REG_DWORD_BIG_ENDIAN:
44                 result = "REG_DWORD_BIG_ENDIAN";
45                 break;
46         case REG_LINK:
47                 result = "REG_LINK";
48                 break;
49         case REG_MULTI_SZ:
50                 result = "REG_MULTI_SZ";
51                 break;
52         case REG_RESOURCE_LIST:
53                 result = "REG_RESOURCE_LIST";
54                 break;
55         case REG_FULL_RESOURCE_DESCRIPTOR:
56                 result = "REG_FULL_RESOURCE_DESCRIPTOR";
57                 break;
58         case REG_RESOURCE_REQUIREMENTS_LIST:
59                 result = "REG_RESOURCE_REQUIREMENTS_LIST";
60                 break;
61         case REG_QWORD:
62                 result = "REG_QWORD";
63                 break;
64         default:
65                 result = "REG TYPE IS UNKNOWN";
66                 break;
67         }
68         return result;
69 }
70
71 WERROR reg_pull_multi_sz(TALLOC_CTX *mem_ctx, const void *buf, size_t len,
72                          uint32 *num_values, char ***values)
73 {
74         const smb_ucs2_t *p = (const smb_ucs2_t *)buf;
75         *num_values = 0;
76
77         /*
78          * Make sure that a talloc context for the strings retrieved exists
79          */
80
81         if (!(*values = TALLOC_ARRAY(mem_ctx, char *, 1))) {
82                 return WERR_NOMEM;
83         }
84
85         len /= 2;               /* buf is a set of UCS2 strings */
86
87         while (len > 0) {
88                 char *val;
89                 size_t dstlen, thislen;
90
91                 thislen = strnlen_w(p, len) + 1;
92                 dstlen = convert_string_allocate(*values, CH_UTF16LE, CH_UNIX,
93                                                  p, thislen*2, (void *)&val,
94                                                  True);
95                 if (dstlen == (size_t)-1) {
96                         TALLOC_FREE(*values);
97                         return WERR_NOMEM;
98                 }
99
100                 ADD_TO_ARRAY(*values, char *, val, values, num_values);
101                 if (*values == NULL) {
102                         return WERR_NOMEM;
103                 }
104
105                 p += thislen;
106                 len -= thislen;
107         }
108
109         return WERR_OK;
110 }
111
112 WERROR registry_pull_value(TALLOC_CTX *mem_ctx,
113                            struct registry_value **pvalue,
114                            enum winreg_Type type, uint8 *data,
115                            uint32 size, uint32 length)
116 {
117         struct registry_value *value;
118         WERROR err;
119
120         if (!(value = TALLOC_ZERO_P(mem_ctx, struct registry_value))) {
121                 return WERR_NOMEM;
122         }
123
124         value->type = type;
125
126         switch (type) {
127         case REG_DWORD:
128                 if ((size != 4) || (length != 4)) {
129                         err = WERR_INVALID_PARAM;
130                         goto error;
131                 }
132                 value->v.dword = IVAL(data, 0);
133                 break;
134         case REG_SZ:
135         case REG_EXPAND_SZ:
136         {
137                 /*
138                  * Make sure we get a NULL terminated string for
139                  * convert_string_talloc().
140                  */
141
142                 smb_ucs2_t *tmp;
143                 uint32 num_ucs2 = length / 2;
144
145                 if ((length % 2) != 0) {
146                         err = WERR_INVALID_PARAM;
147                         goto error;
148                 }
149
150                 if (!(tmp = SMB_MALLOC_ARRAY(smb_ucs2_t, num_ucs2+1))) {
151                         err = WERR_NOMEM;
152                         goto error;
153                 }
154
155                 memcpy((void *)tmp, (const void *)data, length);
156                 tmp[num_ucs2] = 0;
157
158                 value->v.sz.len = convert_string_talloc(
159                         value, CH_UTF16LE, CH_UNIX, tmp, length+2,
160                         &value->v.sz.str, False);
161
162                 SAFE_FREE(tmp);
163
164                 if (value->v.sz.len == (size_t)-1) {
165                         err = WERR_INVALID_PARAM;
166                         goto error;
167                 }
168                 break;
169         }
170         case REG_MULTI_SZ:
171                 err = reg_pull_multi_sz(value, (void *)data, length,
172                                         &value->v.multi_sz.num_strings,
173                                         &value->v.multi_sz.strings);
174                 if (!(W_ERROR_IS_OK(err))) {
175                         goto error;
176                 }
177                 break;
178         case REG_BINARY:
179                 value->v.binary.data = talloc_move(value, &data);
180                 value->v.binary.length = length;
181                 break;
182         default:
183                 err = WERR_INVALID_PARAM;
184                 goto error;
185         }
186
187         *pvalue = value;
188         return WERR_OK;
189
190  error:
191         TALLOC_FREE(value);
192         return err;
193 }
194
195 WERROR registry_push_value(TALLOC_CTX *mem_ctx,
196                            const struct registry_value *value,
197                            DATA_BLOB *presult)
198 {
199         switch (value->type) {
200         case REG_DWORD: {
201                 char buf[4];
202                 SIVAL(buf, 0, value->v.dword);
203                 *presult = data_blob_talloc(mem_ctx, (void *)buf, 4);
204                 if (presult->data == NULL) {
205                         return WERR_NOMEM;
206                 }
207                 break;
208         }
209         case REG_SZ:
210         case REG_EXPAND_SZ: {
211                 presult->length = convert_string_talloc(
212                         mem_ctx, CH_UNIX, CH_UTF16LE, value->v.sz.str,
213                         MIN(value->v.sz.len, strlen(value->v.sz.str)+1),
214                         (void *)&(presult->data), False);
215                 if (presult->length == (size_t)-1) {
216                         return WERR_NOMEM;
217                 }
218                 break;
219         }
220         default:
221                 return WERR_INVALID_PARAM;
222         }
223
224         return WERR_OK;
225 }