mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 16:45:48 +00:00
reg: Split 'add' functions from reg.c.
Signed-off-by: Hugh McMaster <hugh.mcmaster@outlook.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
81a3eecc3c
commit
7e7d92d5e9
|
@ -5,6 +5,7 @@ DELAYIMPORTS = user32
|
|||
EXTRADLLFLAGS = -mconsole -municode -mno-cygwin
|
||||
|
||||
C_SRCS = \
|
||||
add.c \
|
||||
delete.c \
|
||||
export.c \
|
||||
import.c \
|
||||
|
|
213
programs/reg/add.c
Normal file
213
programs/reg/add.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright 2016-2017, 2021 Hugh McMaster
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <wine/heap.h>
|
||||
#include "reg.h"
|
||||
|
||||
static DWORD wchar_get_type(const WCHAR *type_name)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if (!type_name)
|
||||
return REG_SZ;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(type_rels); i++)
|
||||
{
|
||||
if (!wcsicmp(type_rels[i].name, type_name))
|
||||
return type_rels[i].type;
|
||||
}
|
||||
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
/* hexchar_to_byte from programs/regedit/hexedit.c */
|
||||
static inline BYTE hexchar_to_byte(WCHAR ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch - '0';
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
return ch - 'a' + 10;
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
return ch - 'A' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static LPBYTE get_regdata(const WCHAR *data, DWORD reg_type, WCHAR separator, DWORD *reg_count)
|
||||
{
|
||||
static const WCHAR empty;
|
||||
LPBYTE out_data = NULL;
|
||||
*reg_count = 0;
|
||||
|
||||
if (!data) data = ∅
|
||||
|
||||
switch (reg_type)
|
||||
{
|
||||
case REG_NONE:
|
||||
case REG_SZ:
|
||||
case REG_EXPAND_SZ:
|
||||
{
|
||||
*reg_count = (lstrlenW(data) + 1) * sizeof(WCHAR);
|
||||
out_data = heap_xalloc(*reg_count);
|
||||
lstrcpyW((LPWSTR)out_data,data);
|
||||
break;
|
||||
}
|
||||
case REG_DWORD:
|
||||
/* case REG_DWORD_LITTLE_ENDIAN: */
|
||||
case REG_DWORD_BIG_ENDIAN: /* Yes, this is correct! */
|
||||
{
|
||||
LPWSTR rest;
|
||||
unsigned long val;
|
||||
val = wcstoul(data, &rest, (towlower(data[1]) == 'x') ? 16 : 10);
|
||||
if (*rest || data[0] == '-' || (val == ~0u && errno == ERANGE)) {
|
||||
output_message(STRING_MISSING_INTEGER);
|
||||
break;
|
||||
}
|
||||
*reg_count = sizeof(DWORD);
|
||||
out_data = heap_xalloc(*reg_count);
|
||||
((LPDWORD)out_data)[0] = val;
|
||||
break;
|
||||
}
|
||||
case REG_BINARY:
|
||||
{
|
||||
BYTE hex0, hex1;
|
||||
int i = 0, destByteIndex = 0, datalen = lstrlenW(data);
|
||||
*reg_count = ((datalen + datalen % 2) / 2) * sizeof(BYTE);
|
||||
out_data = heap_xalloc(*reg_count);
|
||||
if(datalen % 2)
|
||||
{
|
||||
hex1 = hexchar_to_byte(data[i++]);
|
||||
if(hex1 == 0xFF)
|
||||
goto no_hex_data;
|
||||
out_data[destByteIndex++] = hex1;
|
||||
}
|
||||
for(;i + 1 < datalen;i += 2)
|
||||
{
|
||||
hex0 = hexchar_to_byte(data[i]);
|
||||
hex1 = hexchar_to_byte(data[i + 1]);
|
||||
if(hex0 == 0xFF || hex1 == 0xFF)
|
||||
goto no_hex_data;
|
||||
out_data[destByteIndex++] = (hex0 << 4) | hex1;
|
||||
}
|
||||
break;
|
||||
no_hex_data:
|
||||
/* cleanup, print error */
|
||||
heap_free(out_data);
|
||||
output_message(STRING_MISSING_HEXDATA);
|
||||
out_data = NULL;
|
||||
break;
|
||||
}
|
||||
case REG_MULTI_SZ:
|
||||
{
|
||||
int i, destindex, len = lstrlenW(data);
|
||||
WCHAR *buffer = heap_xalloc((len + 2) * sizeof(WCHAR));
|
||||
|
||||
for (i = 0, destindex = 0; i < len; i++, destindex++)
|
||||
{
|
||||
if (!separator && data[i] == '\\' && data[i + 1] == '0')
|
||||
{
|
||||
buffer[destindex] = 0;
|
||||
i++;
|
||||
}
|
||||
else if (data[i] == separator)
|
||||
buffer[destindex] = 0;
|
||||
else
|
||||
buffer[destindex] = data[i];
|
||||
|
||||
if (destindex && !buffer[destindex - 1] && (!buffer[destindex] || destindex == 1))
|
||||
{
|
||||
heap_free(buffer);
|
||||
output_message(STRING_INVALID_STRING);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
buffer[destindex] = 0;
|
||||
if (destindex && buffer[destindex - 1])
|
||||
buffer[++destindex] = 0;
|
||||
*reg_count = (destindex + 1) * sizeof(WCHAR);
|
||||
return (BYTE *)buffer;
|
||||
}
|
||||
default:
|
||||
output_message(STRING_UNHANDLED_TYPE, reg_type, data);
|
||||
}
|
||||
|
||||
return out_data;
|
||||
}
|
||||
|
||||
int reg_add(HKEY root, WCHAR *path, WCHAR *value_name, BOOL value_empty,
|
||||
WCHAR *type, WCHAR separator, WCHAR *data, BOOL force)
|
||||
{
|
||||
HKEY key;
|
||||
|
||||
if (RegCreateKeyW(root, path, &key) != ERROR_SUCCESS)
|
||||
{
|
||||
output_message(STRING_INVALID_KEY);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (value_name || value_empty || data)
|
||||
{
|
||||
DWORD reg_type;
|
||||
DWORD reg_count = 0;
|
||||
BYTE* reg_data = NULL;
|
||||
|
||||
if (!force)
|
||||
{
|
||||
if (RegQueryValueExW(key, value_name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||||
{
|
||||
if (!ask_confirm(STRING_OVERWRITE_VALUE, value_name))
|
||||
{
|
||||
RegCloseKey(key);
|
||||
output_message(STRING_CANCELLED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reg_type = wchar_get_type(type);
|
||||
if (reg_type == ~0u)
|
||||
{
|
||||
RegCloseKey(key);
|
||||
output_message(STRING_UNSUPPORTED_TYPE, type);
|
||||
return 1;
|
||||
}
|
||||
if ((reg_type == REG_DWORD || reg_type == REG_DWORD_BIG_ENDIAN) && !data)
|
||||
{
|
||||
RegCloseKey(key);
|
||||
output_message(STRING_INVALID_CMDLINE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(reg_data = get_regdata(data, reg_type, separator, ®_count)))
|
||||
{
|
||||
RegCloseKey(key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
RegSetValueExW(key, value_name, 0, reg_type, reg_data, reg_count);
|
||||
heap_free(reg_data);
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
output_message(STRING_SUCCESS);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -17,8 +17,6 @@
|
|||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <wine/debug.h>
|
||||
#include <wine/heap.h>
|
||||
|
@ -213,136 +211,6 @@ HKEY path_get_rootkey(const WCHAR *path)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static DWORD wchar_get_type(const WCHAR *type_name)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if (!type_name)
|
||||
return REG_SZ;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(type_rels); i++)
|
||||
{
|
||||
if (!wcsicmp(type_rels[i].name, type_name))
|
||||
return type_rels[i].type;
|
||||
}
|
||||
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
/* hexchar_to_byte from programs/regedit/hexedit.c */
|
||||
static inline BYTE hexchar_to_byte(WCHAR ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch - '0';
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
return ch - 'a' + 10;
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
return ch - 'A' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static LPBYTE get_regdata(const WCHAR *data, DWORD reg_type, WCHAR separator, DWORD *reg_count)
|
||||
{
|
||||
static const WCHAR empty;
|
||||
LPBYTE out_data = NULL;
|
||||
*reg_count = 0;
|
||||
|
||||
if (!data) data = ∅
|
||||
|
||||
switch (reg_type)
|
||||
{
|
||||
case REG_NONE:
|
||||
case REG_SZ:
|
||||
case REG_EXPAND_SZ:
|
||||
{
|
||||
*reg_count = (lstrlenW(data) + 1) * sizeof(WCHAR);
|
||||
out_data = heap_xalloc(*reg_count);
|
||||
lstrcpyW((LPWSTR)out_data,data);
|
||||
break;
|
||||
}
|
||||
case REG_DWORD:
|
||||
/* case REG_DWORD_LITTLE_ENDIAN: */
|
||||
case REG_DWORD_BIG_ENDIAN: /* Yes, this is correct! */
|
||||
{
|
||||
LPWSTR rest;
|
||||
unsigned long val;
|
||||
val = wcstoul(data, &rest, (towlower(data[1]) == 'x') ? 16 : 10);
|
||||
if (*rest || data[0] == '-' || (val == ~0u && errno == ERANGE)) {
|
||||
output_message(STRING_MISSING_INTEGER);
|
||||
break;
|
||||
}
|
||||
*reg_count = sizeof(DWORD);
|
||||
out_data = heap_xalloc(*reg_count);
|
||||
((LPDWORD)out_data)[0] = val;
|
||||
break;
|
||||
}
|
||||
case REG_BINARY:
|
||||
{
|
||||
BYTE hex0, hex1;
|
||||
int i = 0, destByteIndex = 0, datalen = lstrlenW(data);
|
||||
*reg_count = ((datalen + datalen % 2) / 2) * sizeof(BYTE);
|
||||
out_data = heap_xalloc(*reg_count);
|
||||
if(datalen % 2)
|
||||
{
|
||||
hex1 = hexchar_to_byte(data[i++]);
|
||||
if(hex1 == 0xFF)
|
||||
goto no_hex_data;
|
||||
out_data[destByteIndex++] = hex1;
|
||||
}
|
||||
for(;i + 1 < datalen;i += 2)
|
||||
{
|
||||
hex0 = hexchar_to_byte(data[i]);
|
||||
hex1 = hexchar_to_byte(data[i + 1]);
|
||||
if(hex0 == 0xFF || hex1 == 0xFF)
|
||||
goto no_hex_data;
|
||||
out_data[destByteIndex++] = (hex0 << 4) | hex1;
|
||||
}
|
||||
break;
|
||||
no_hex_data:
|
||||
/* cleanup, print error */
|
||||
heap_free(out_data);
|
||||
output_message(STRING_MISSING_HEXDATA);
|
||||
out_data = NULL;
|
||||
break;
|
||||
}
|
||||
case REG_MULTI_SZ:
|
||||
{
|
||||
int i, destindex, len = lstrlenW(data);
|
||||
WCHAR *buffer = heap_xalloc((len + 2) * sizeof(WCHAR));
|
||||
|
||||
for (i = 0, destindex = 0; i < len; i++, destindex++)
|
||||
{
|
||||
if (!separator && data[i] == '\\' && data[i + 1] == '0')
|
||||
{
|
||||
buffer[destindex] = 0;
|
||||
i++;
|
||||
}
|
||||
else if (data[i] == separator)
|
||||
buffer[destindex] = 0;
|
||||
else
|
||||
buffer[destindex] = data[i];
|
||||
|
||||
if (destindex && !buffer[destindex - 1] && (!buffer[destindex] || destindex == 1))
|
||||
{
|
||||
heap_free(buffer);
|
||||
output_message(STRING_INVALID_STRING);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
buffer[destindex] = 0;
|
||||
if (destindex && buffer[destindex - 1])
|
||||
buffer[++destindex] = 0;
|
||||
*reg_count = (destindex + 1) * sizeof(WCHAR);
|
||||
return (BYTE *)buffer;
|
||||
}
|
||||
default:
|
||||
output_message(STRING_UNHANDLED_TYPE, reg_type, data);
|
||||
}
|
||||
|
||||
return out_data;
|
||||
}
|
||||
|
||||
static BOOL sane_path(const WCHAR *key)
|
||||
{
|
||||
unsigned int i = lstrlenW(key);
|
||||
|
@ -362,66 +230,6 @@ static BOOL sane_path(const WCHAR *key)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static int reg_add(HKEY root, WCHAR *path, WCHAR *value_name, BOOL value_empty,
|
||||
WCHAR *type, WCHAR separator, WCHAR *data, BOOL force)
|
||||
{
|
||||
HKEY key;
|
||||
|
||||
if (RegCreateKeyW(root, path, &key) != ERROR_SUCCESS)
|
||||
{
|
||||
output_message(STRING_INVALID_KEY);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (value_name || value_empty || data)
|
||||
{
|
||||
DWORD reg_type;
|
||||
DWORD reg_count = 0;
|
||||
BYTE* reg_data = NULL;
|
||||
|
||||
if (!force)
|
||||
{
|
||||
if (RegQueryValueExW(key, value_name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||||
{
|
||||
if (!ask_confirm(STRING_OVERWRITE_VALUE, value_name))
|
||||
{
|
||||
RegCloseKey(key);
|
||||
output_message(STRING_CANCELLED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reg_type = wchar_get_type(type);
|
||||
if (reg_type == ~0u)
|
||||
{
|
||||
RegCloseKey(key);
|
||||
output_message(STRING_UNSUPPORTED_TYPE, type);
|
||||
return 1;
|
||||
}
|
||||
if ((reg_type == REG_DWORD || reg_type == REG_DWORD_BIG_ENDIAN) && !data)
|
||||
{
|
||||
RegCloseKey(key);
|
||||
output_message(STRING_INVALID_CMDLINE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(reg_data = get_regdata(data, reg_type, separator, ®_count)))
|
||||
{
|
||||
RegCloseKey(key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
RegSetValueExW(key, value_name, 0, reg_type, reg_data, reg_count);
|
||||
heap_free(reg_data);
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
output_message(STRING_SUCCESS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
|
||||
{
|
||||
WCHAR *subkey_path;
|
||||
|
|
|
@ -41,6 +41,10 @@ HKEY path_get_rootkey(const WCHAR *path);
|
|||
WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len);
|
||||
BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path, WCHAR **long_key);
|
||||
|
||||
/* add.c */
|
||||
int reg_add(HKEY root, WCHAR *path, WCHAR *value_name, BOOL value_empty,
|
||||
WCHAR *type, WCHAR separator, WCHAR *data, BOOL force);
|
||||
|
||||
/* delete.c */
|
||||
int reg_delete(HKEY root, WCHAR *path, WCHAR *key_name, WCHAR *value_name,
|
||||
BOOL value_empty, BOOL value_all, BOOL force);
|
||||
|
|
Loading…
Reference in a new issue