Add _krb5_store_string_to_reg_value() for Windows

The new _krb5_store_string_to_reg_value() function permits
the caller to create REG_SZ, REG_EXPAND_SZ, REG_DWORD, and
REG_MULTI_SZ entries in the registry.

Change-Id: Ib5740ad07209618d8ea4c0bf3c75615f27e98b4e
This commit is contained in:
Jeffrey Altman
2011-09-26 01:58:29 -04:00
parent d6bff3199d
commit 132693df5a
2 changed files with 172 additions and 1 deletions

View File

@@ -51,7 +51,8 @@ DLLSDKDEPS= \
$(PTHREAD_LIB) \
secur32.lib \
shell32.lib \
dnsapi.lib
dnsapi.lib \
shlwapi.lib
DEF=$(OBJ)\heimdal.def

View File

@@ -35,9 +35,179 @@
#error config_reg.c is only for Windows
#endif
#include <shlwapi.h>
#ifndef MAX_DWORD
#define MAX_DWORD 0xFFFFFFFF
#endif
#define REGPATH_KERBEROS "SOFTWARE\\Kerberos"
#define REGPATH_HEIMDAL "SOFTWARE\\Heimdal"
/**
* Store a string as a registry value of the specified type
*
* The following registry types are handled:
*
* - REG_DWORD: The string is converted to a number.
*
* - REG_SZ: The string is stored as is.
*
* - REG_EXPAND_SZ: The string is stored as is.
*
* - REG_MULTI_SZ:
*
* . If a separator is specified, the input string is broken
* up into multiple strings and stored as a multi-sz.
*
* . If no separator is provided, the input string is stored
* as a multi-sz.
*
* - REG_NONE:
*
* . If the string is all numeric, it will be stored as a
* REG_DWORD.
*
* . Otherwise, the string is stored as a REG_SZ.
*
* Other types are rejected.
*
* If cb_data is MAX_DWORD, the string pointed to by data must be nul-terminated
* otherwise a buffer overrun will occur.
*
* @param [in]valuename Name of the registry value to be modified or created
* @param [in]type Type of the value. REG_NONE if unknown
* @param [in]data The input string to be stored in the registry.
* @param [in]cb_data Size of the input string in bytes. MAX_DWORD if unknown.
* @param [in]separator Separator character for parsing strings.
*
* @retval 0 if success or non-zero on error.
* If non-zero is returned, an error message has been set using
* krb5_set_error_message().
*
*/
int
_krb5_store_string_to_reg_value(krb5_context context,
HKEY key, const char * valuename,
DWORD type, const char *data, DWORD cb_data,
const char * separator)
{
LONG rcode;
DWORD dwData;
BYTE static_buffer[16384];
BYTE *pbuffer = &static_buffer[0];
if (data == NULL)
{
if (context)
krb5_set_error_message(context, 0,
"'data' must not be NULL");
return -1;
}
if (cb_data == MAX_DWORD)
{
cb_data = (DWORD)strlen(data) + 1;
}
else if ((type == REG_MULTI_SZ && cb_data >= sizeof(static_buffer) - 1) ||
cb_data >= sizeof(static_buffer))
{
if (context)
krb5_set_error_message(context, 0, "cb_data too big");
return -1;
}
else if (data[cb_data-1] != '\0')
{
memcpy(static_buffer, data, cb_data);
static_buffer[cb_data++] = '\0';
if (type == REG_MULTI_SZ)
static_buffer[cb_data++] = '\0';
data = static_buffer;
}
if (type == REG_NONE)
{
/*
* If input is all numeric, convert to DWORD and save as REG_DWORD.
* Otherwise, store as REG_SZ.
*/
if ( StrToIntExA( data, STIF_SUPPORT_HEX, &dwData) )
{
type = REG_DWORD;
} else {
type = REG_SZ;
}
}
switch (type) {
case REG_SZ:
case REG_EXPAND_SZ:
rcode = RegSetValueEx(key, valuename, 0, type, data, cb_data);
if (rcode)
{
if (context)
krb5_set_error_message(context, 0,
"Unexpected error when setting registry value %s gle 0x%x",
valuename,
GetLastError());
return -1;
}
break;
case REG_MULTI_SZ:
if (separator && *separator)
{
int i;
char *cp;
if (data != static_buffer)
static_buffer[cb_data++] = '\0';
for ( cp = static_buffer; cp < static_buffer+cb_data; cp++)
{
if (*cp == *separator)
*cp = '\0';
}
rcode = RegSetValueEx(key, valuename, 0, type, data, cb_data);
if (rcode)
{
if (context)
krb5_set_error_message(context, 0,
"Unexpected error when setting registry value %s gle 0x%x",
valuename,
GetLastError());
return -1;
}
}
break;
case REG_DWORD:
if ( !StrToIntExA( data, STIF_SUPPORT_HEX, &dwData) )
{
if (context)
krb5_set_error_message(context, 0,
"Unexpected error when parsing %s as number gle 0x%x",
data,
GetLastError());
}
rcode = RegSetValueEx(key, valuename, 0, type, dwData, sizeof(DWORD));
if (rcode)
{
if (context)
krb5_set_error_message(context, 0,
"Unexpected error when setting registry value %s gle 0x%x",
valuename,
GetLastError());
return -1;
}
break;
default:
return -1;
}
return 0;
}
/**
* Parse a registry value as a string
*