/* 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 # 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