blob: 5a06f43e92465ed4a01bc32bffe2717a55bc6302 [file] [log] [blame]
/*
Copyright Paul Lin 2003. Copyright 2006 Bojan Resnik.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
# include "jam.h"
# if defined( OS_NT ) || defined( OS_CYGWIN )
# include "lists.h"
# include "newstr.h"
# include "parse.h"
# include "frames.h"
# include "strings.h"
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# define MAX_REGISTRY_DATA_LENGTH 4096
# define MAX_REGISTRY_KEYNAME_LENGTH 256
# define MAX_REGISTRY_VALUENAME_LENGTH 16384
typedef struct
{
LPCSTR name;
HKEY value;
} KeyMap;
static const KeyMap dlRootKeys[] = {
{ "HKLM", HKEY_LOCAL_MACHINE },
{ "HKCU", HKEY_CURRENT_USER },
{ "HKCR", HKEY_CLASSES_ROOT },
{ "HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE },
{ "HKEY_CURRENT_USER", HKEY_CURRENT_USER },
{ "HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT },
{ 0, 0 }
};
static HKEY get_key(char const** path)
{
const KeyMap *p;
for (p = dlRootKeys; p->name; ++p)
{
int n = strlen(p->name);
if (!strncmp(*path,p->name,n))
{
if ((*path)[n] == '\\' || (*path)[n] == 0)
{
*path += n + 1;
break;
}
}
}
return p->value;
}
LIST*
builtin_system_registry(
PARSE *parse,
FRAME *frame )
{
char const* path = lol_get(frame->args, 0)->string;
LIST* result = L0;
HKEY key = get_key(&path);
if (
key != 0
&& ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key)
)
{
DWORD type;
BYTE data[MAX_REGISTRY_DATA_LENGTH];
DWORD len = sizeof(data);
LIST const* const field = lol_get(frame->args, 1);
if ( ERROR_SUCCESS ==
RegQueryValueEx(key, field ? field->string : 0, 0, &type, data, &len) )
{
switch (type)
{
case REG_EXPAND_SZ:
{
long len;
string expanded[1];
string_new(expanded);
while (
(len = ExpandEnvironmentStrings(
(LPCSTR)data, expanded->value, expanded->capacity))
> expanded->capacity
)
string_reserve(expanded, len);
expanded->size = len - 1;
result = list_new( result, newstr(expanded->value) );
string_free( expanded );
}
break;
case REG_MULTI_SZ:
{
char* s;
for (s = (char*)data; *s; s += strlen(s) + 1)
result = list_new( result, newstr(s) );
}
break;
case REG_DWORD:
{
char buf[100];
sprintf( buf, "%u", *(PDWORD)data );
result = list_new( result, newstr(buf) );
}
break;
case REG_SZ:
result = list_new( result, newstr((char*)data) );
break;
}
}
RegCloseKey(key);
}
return result;
}
static LIST* get_subkey_names(HKEY key, char const* path)
{
LIST* result = 0;
if ( ERROR_SUCCESS ==
RegOpenKeyEx(key, path, 0, KEY_ENUMERATE_SUB_KEYS, &key)
)
{
char name[MAX_REGISTRY_KEYNAME_LENGTH];
DWORD name_size = sizeof(name);
DWORD index;
FILETIME last_write_time;
for ( index = 0;
ERROR_SUCCESS == RegEnumKeyEx(
key, index, name, &name_size, 0, 0, 0, &last_write_time);
++index,
name_size = sizeof(name)
)
{
name[name_size] = 0;
result = list_append(result, list_new(0, newstr(name)));
}
RegCloseKey(key);
}
return result;
}
static LIST* get_value_names(HKEY key, char const* path)
{
LIST* result = 0;
if ( ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key) )
{
char name[MAX_REGISTRY_VALUENAME_LENGTH];
DWORD name_size = sizeof(name);
DWORD index;
for ( index = 0;
ERROR_SUCCESS == RegEnumValue(
key, index, name, &name_size, 0, 0, 0, 0);
++index,
name_size = sizeof(name)
)
{
name[name_size] = 0;
result = list_append(result, list_new(0, newstr(name)));
}
RegCloseKey(key);
}
return result;
}
LIST*
builtin_system_registry_names(
PARSE *parse,
FRAME *frame )
{
char const* path = lol_get(frame->args, 0)->string;
char const* result_type = lol_get(frame->args, 1)->string;
HKEY key = get_key(&path);
if ( !strcmp(result_type, "subkeys") )
return get_subkey_names(key, path);
if ( !strcmp(result_type, "values") )
return get_value_names(key, path);
return 0;
}
# endif