2 Unix SMB/CIFS implementation.
3 Reading Registry.pol PReg registry files
5 Copyright (C) Wilco Baan Hofman 2006-2008
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "lib/registry/registry.h"
24 #include "system/filesys.h"
25 #include "librpc/gen_ndr/winreg.h"
26 #include "lib/util/sys_rw.h"
36 static WERROR preg_read_utf16(int fd, char *c)
40 if (read(fd, &v, sizeof(uint16_t)) < sizeof(uint16_t)) {
41 return WERR_GEN_FAILURE;
46 static WERROR preg_write_utf16(int fd, const char *string)
51 for (i = 0; i < strlen(string); i+=size) {
52 v = next_codepoint(&string[i], &size);
53 if (write(fd, &v, sizeof(uint16_t)) < sizeof(uint16_t)) {
54 return WERR_GEN_FAILURE;
59 /* PReg does not support adding keys. */
60 static WERROR reg_preg_diff_add_key(void *_data, const char *key_name)
65 static WERROR reg_preg_diff_set_value(void *_data, const char *key_name,
66 const char *value_name,
67 uint32_t value_type, DATA_BLOB value_data)
69 struct preg_data *data = (struct preg_data *)_data;
72 preg_write_utf16(data->fd, "[");
73 preg_write_utf16(data->fd, key_name);
74 preg_write_utf16(data->fd, ";");
75 preg_write_utf16(data->fd, value_name);
76 preg_write_utf16(data->fd, ";");
77 SIVAL(&buf, 0, value_type);
78 sys_write_v(data->fd, &buf, sizeof(uint32_t));
79 preg_write_utf16(data->fd, ";");
80 SIVAL(&buf, 0, value_data.length);
81 sys_write_v(data->fd, &buf, sizeof(uint32_t));
82 preg_write_utf16(data->fd, ";");
83 sys_write_v(data->fd, value_data.data, value_data.length);
84 preg_write_utf16(data->fd, "]");
89 static WERROR reg_preg_diff_del_key(void *_data, const char *key_name)
91 struct preg_data *data = (struct preg_data *)_data;
96 parent_name = talloc_strndup(data->ctx, key_name,
97 strrchr(key_name, '\\')-key_name);
98 W_ERROR_HAVE_NO_MEMORY(parent_name);
99 blob.data = (uint8_t*)talloc_strndup(data->ctx,
100 key_name+(strrchr(key_name, '\\')-key_name)+1,
101 strlen(key_name)-(strrchr(key_name, '\\')-key_name));
102 W_ERROR_HAVE_NO_MEMORY(blob.data);
103 blob.length = strlen((char *)blob.data)+1;
106 /* FIXME: These values should be accumulated to be written at done(). */
107 werr = reg_preg_diff_set_value(data, parent_name, "**DeleteKeys",
110 talloc_free(parent_name);
111 talloc_free(blob.data);
116 static WERROR reg_preg_diff_del_value(void *_data, const char *key_name,
117 const char *value_name)
119 struct preg_data *data = (struct preg_data *)_data;
124 val = talloc_asprintf(data->ctx, "**Del.%s", value_name);
125 W_ERROR_HAVE_NO_MEMORY(val);
126 blob.data = (uint8_t *)talloc(data->ctx, uint32_t);
127 W_ERROR_HAVE_NO_MEMORY(blob.data);
128 SIVAL(blob.data, 0, 0);
129 blob.length = sizeof(uint32_t);
131 werr = reg_preg_diff_set_value(data, key_name, val, REG_DWORD, blob);
134 talloc_free(blob.data);
139 static WERROR reg_preg_diff_del_all_values(void *_data, const char *key_name)
141 struct preg_data *data = (struct preg_data *)_data;
145 blob.data = (uint8_t *)talloc(data->ctx, uint32_t);
146 W_ERROR_HAVE_NO_MEMORY(blob.data);
147 SIVAL(blob.data, 0, 0);
148 blob.length = sizeof(uint32_t);
150 werr = reg_preg_diff_set_value(data, key_name, "**DelVals.", REG_DWORD,
153 talloc_free(blob.data);
158 static WERROR reg_preg_diff_done(void *_data)
160 struct preg_data *data = (struct preg_data *)_data;
170 _PUBLIC_ WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename,
171 struct reg_diff_callbacks **callbacks,
172 void **callback_data)
174 struct preg_data *data;
181 data = talloc_zero(ctx, struct preg_data);
182 *callback_data = data;
185 data->fd = open(filename, O_CREAT|O_WRONLY, 0755);
187 DEBUG(0, ("Unable to open %s\n", filename));
188 return WERR_FILE_NOT_FOUND;
191 data->fd = STDOUT_FILENO;
194 memcpy(preg_header.hdr, "PReg", sizeof(preg_header.hdr));
195 SIVAL(&preg_header.version, 0, 1);
196 sys_write_v(data->fd, (uint8_t *)&preg_header, sizeof(preg_header));
200 *callbacks = talloc(ctx, struct reg_diff_callbacks);
202 (*callbacks)->add_key = reg_preg_diff_add_key;
203 (*callbacks)->del_key = reg_preg_diff_del_key;
204 (*callbacks)->set_value = reg_preg_diff_set_value;
205 (*callbacks)->del_value = reg_preg_diff_del_value;
206 (*callbacks)->del_all_values = reg_preg_diff_del_all_values;
207 (*callbacks)->done = reg_preg_diff_done;
214 _PUBLIC_ WERROR reg_preg_diff_load(int fd,
215 const struct reg_diff_callbacks *callbacks,
223 size_t buf_size = 1024;
225 TALLOC_CTX *mem_ctx = talloc_init("reg_preg_diff_load");
226 WERROR ret = WERR_OK;
228 buf = talloc_array(mem_ctx, char, buf_size);
231 /* Read first 8 bytes (the header) */
232 if (read(fd, &preg_header, sizeof(preg_header)) != sizeof(preg_header)) {
233 DEBUG(0, ("Could not read PReg file: %s\n",
235 ret = WERR_GEN_FAILURE;
238 preg_header.version = IVAL(&preg_header.version, 0);
240 if (strncmp(preg_header.hdr, "PReg", 4) != 0) {
241 DEBUG(0, ("This file is not a valid preg registry file\n"));
242 ret = WERR_GEN_FAILURE;
245 if (preg_header.version > 1) {
246 DEBUG(0, ("Warning: file format version is higher than expected.\n"));
249 /* Read the entries */
251 uint32_t value_type, length;
253 char *value_name = NULL;
254 DATA_BLOB data = {NULL, 0};
256 if (!W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr))) {
259 if (*buf_ptr != '[') {
260 DEBUG(0, ("Error in PReg file.\n"));
261 ret = WERR_GEN_FAILURE;
267 while (W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) &&
268 *buf_ptr != ';' && buf_ptr-buf < buf_size) {
271 buf[buf_ptr-buf] = '\0';
272 key = talloc_strdup(mem_ctx, buf);
276 while (W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) &&
277 *buf_ptr != ';' && buf_ptr-buf < buf_size) {
280 buf[buf_ptr-buf] = '\0';
281 value_name = talloc_strdup(mem_ctx, buf);
284 if (read(fd, &value_type, sizeof(uint32_t)) < sizeof(uint32_t)) {
285 DEBUG(0, ("Error while reading PReg\n"));
286 ret = WERR_GEN_FAILURE;
289 value_type = IVAL(&value_type, 0);
291 /* Read past delimiter */
293 if (!(W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) &&
294 *buf_ptr == ';') && buf_ptr-buf < buf_size) {
295 DEBUG(0, ("Error in PReg file.\n"));
296 ret = WERR_GEN_FAILURE;
300 /* Get data length */
301 if (read(fd, &length, sizeof(uint32_t)) < sizeof(uint32_t)) {
302 DEBUG(0, ("Error while reading PReg\n"));
303 ret = WERR_GEN_FAILURE;
306 length = IVAL(&length, 0);
308 /* Read past delimiter */
310 if (!(W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) &&
311 *buf_ptr == ';') && buf_ptr-buf < buf_size) {
312 DEBUG(0, ("Error in PReg file.\n"));
313 ret = WERR_GEN_FAILURE;
319 if (length < buf_size &&
320 read(fd, buf_ptr, length) != length) {
321 DEBUG(0, ("Error while reading PReg\n"));
322 ret = WERR_GEN_FAILURE;
325 data = data_blob_talloc(mem_ctx, buf, length);
327 /* Check if delimiter is in place (whine if it isn't) */
329 if (!(W_ERROR_IS_OK(preg_read_utf16(fd, buf_ptr)) &&
330 *buf_ptr == ']') && buf_ptr-buf < buf_size) {
331 DEBUG(0, ("Warning: Missing ']' in PReg file, expected ']', got '%c' 0x%x.\n",
332 *buf_ptr, *buf_ptr));
335 if (strcasecmp(value_name, "**DelVals") == 0) {
336 callbacks->del_all_values(callback_data, key);
337 } else if (strncasecmp(value_name, "**Del.",6) == 0) {
338 char *p = value_name+6;
340 callbacks->del_value(callback_data, key, p);
341 } else if (strcasecmp(value_name, "**DeleteValues") == 0) {
344 p = (char *) data.data;
346 while ((q = strchr_m(p, ';'))) {
350 callbacks->del_value(callback_data, key, p);
354 callbacks->del_value(callback_data, key, p);
355 } else if (strcasecmp(value_name, "**DeleteKeys") == 0) {
356 char *p, *q, *full_key;
358 p = (char *) data.data;
360 while ((q = strchr_m(p, ';'))) {
364 full_key = talloc_asprintf(mem_ctx, "%s\\%s",
366 callbacks->del_key(callback_data, full_key);
367 talloc_free(full_key);
371 full_key = talloc_asprintf(mem_ctx, "%s\\%s", key, p);
372 callbacks->del_key(callback_data, full_key);
373 talloc_free(full_key);
375 callbacks->add_key(callback_data, key);
376 callbacks->set_value(callback_data, key, value_name,
380 TALLOC_FREE(value_name);
381 data_blob_free(&data);
385 TALLOC_FREE(mem_ctx);