1 /*
2 Copyright Paul Lin 2003. Copyright 2006 Bojan Resnik.
3 Distributed under the Boost Software License, Version 1.0. (See accompanying
4 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 */
6 
7 # include "jam.h"
8 
9 # if defined( OS_NT ) || defined( OS_CYGWIN )
10 
11 # include "lists.h"
12 # include "object.h"
13 # include "parse.h"
14 # include "frames.h"
15 # include "strings.h"
16 
17 # define WIN32_LEAN_AND_MEAN
18 # include <windows.h>
19 
20 # define  MAX_REGISTRY_DATA_LENGTH 4096
21 # define  MAX_REGISTRY_KEYNAME_LENGTH 256
22 # define  MAX_REGISTRY_VALUENAME_LENGTH 16384
23 
24 typedef struct
25 {
26     LPCSTR  name;
27     HKEY    value;
28 } KeyMap;
29 
30 static const KeyMap dlRootKeys[] = {
31     { "HKLM", HKEY_LOCAL_MACHINE },
32     { "HKCU", HKEY_CURRENT_USER },
33     { "HKCR", HKEY_CLASSES_ROOT },
34     { "HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE },
35     { "HKEY_CURRENT_USER", HKEY_CURRENT_USER },
36     { "HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT },
37     { 0, 0 }
38 };
39 
get_key(char const ** path)40 static HKEY get_key(char const** path)
41 {
42     const KeyMap *p;
43 
44     for (p = dlRootKeys; p->name; ++p)
45     {
46         int n = strlen(p->name);
47         if (!strncmp(*path,p->name,n))
48         {
49             if ((*path)[n] == '\\' || (*path)[n] == 0)
50             {
51                 *path += n + 1;
52                 break;
53             }
54         }
55     }
56 
57     return p->value;
58 }
59 
builtin_system_registry(FRAME * frame,int flags)60 LIST * builtin_system_registry( FRAME * frame, int flags )
61 {
62     char const* path = object_str( list_front( lol_get(frame->args, 0) ) );
63     LIST* result = L0;
64     HKEY key = get_key(&path);
65 
66     if (
67         key != 0
68         && ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key)
69     )
70     {
71         DWORD  type;
72         BYTE   data[MAX_REGISTRY_DATA_LENGTH];
73         DWORD  len = sizeof(data);
74         LIST * const field = lol_get(frame->args, 1);
75 
76         if ( ERROR_SUCCESS ==
77              RegQueryValueEx(key, field ? object_str( list_front( field ) ) : 0, 0, &type, data, &len) )
78         {
79             switch (type)
80             {
81 
82              case REG_EXPAND_SZ:
83                  {
84                      long len;
85                      string expanded[1];
86                      string_new(expanded);
87 
88                      while (
89                          (len = ExpandEnvironmentStrings(
90                              (LPCSTR)data, expanded->value, expanded->capacity))
91                          > expanded->capacity
92                      )
93                          string_reserve(expanded, len);
94 
95                      expanded->size = len - 1;
96 
97                      result = list_push_back( result, object_new(expanded->value) );
98                      string_free( expanded );
99                  }
100                  break;
101 
102              case REG_MULTI_SZ:
103                  {
104                      char* s;
105 
106                      for (s = (char*)data; *s; s += strlen(s) + 1)
107                          result = list_push_back( result, object_new(s) );
108 
109                  }
110                  break;
111 
112              case REG_DWORD:
113                  {
114                      char buf[100];
115                      sprintf( buf, "%u", *(PDWORD)data );
116                      result = list_push_back( result, object_new(buf) );
117                  }
118                  break;
119 
120              case REG_SZ:
121                  result = list_push_back( result, object_new( (const char *)data ) );
122                  break;
123             }
124         }
125         RegCloseKey(key);
126     }
127     return  result;
128 }
129 
get_subkey_names(HKEY key,char const * path)130 static LIST* get_subkey_names(HKEY key, char const* path)
131 {
132     LIST* result = 0;
133 
134     if ( ERROR_SUCCESS ==
135          RegOpenKeyEx(key, path, 0, KEY_ENUMERATE_SUB_KEYS, &key)
136     )
137     {
138         char name[MAX_REGISTRY_KEYNAME_LENGTH];
139         DWORD name_size = sizeof(name);
140         DWORD index;
141         FILETIME last_write_time;
142 
143         for ( index = 0;
144               ERROR_SUCCESS == RegEnumKeyEx(
145                   key, index, name, &name_size, 0, 0, 0, &last_write_time);
146               ++index,
147               name_size = sizeof(name)
148         )
149         {
150             name[name_size] = 0;
151             result = list_append(result, list_new(object_new(name)));
152         }
153 
154         RegCloseKey(key);
155     }
156 
157     return result;
158 }
159 
get_value_names(HKEY key,char const * path)160 static LIST* get_value_names(HKEY key, char const* path)
161 {
162     LIST* result = 0;
163 
164     if ( ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key) )
165     {
166         char name[MAX_REGISTRY_VALUENAME_LENGTH];
167         DWORD name_size = sizeof(name);
168         DWORD index;
169 
170         for ( index = 0;
171               ERROR_SUCCESS == RegEnumValue(
172                   key, index, name, &name_size, 0, 0, 0, 0);
173               ++index,
174               name_size = sizeof(name)
175         )
176         {
177             name[name_size] = 0;
178             result = list_append(result, list_new(object_new(name)));
179         }
180 
181         RegCloseKey(key);
182     }
183 
184     return result;
185 }
186 
builtin_system_registry_names(FRAME * frame,int flags)187 LIST * builtin_system_registry_names( FRAME * frame, int flags )
188 {
189     char const* path        = object_str( list_front( lol_get(frame->args, 0) ) );
190     char const* result_type = object_str( list_front( lol_get(frame->args, 1) ) );
191 
192     HKEY key = get_key(&path);
193 
194     if ( !strcmp(result_type, "subkeys") )
195         return get_subkey_names(key, path);
196     if ( !strcmp(result_type, "values") )
197         return get_value_names(key, path);
198     return 0;
199 }
200 
201 # endif
202