Imported Upstream version 201104
[platform/upstream/boost-jam.git] / w32_getreg.c
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 "newstr.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
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
60 LIST*
61 builtin_system_registry(
62     PARSE    *parse,
63     FRAME    *frame )
64 {
65     char const* path = lol_get(frame->args, 0)->string;
66     LIST* result = L0;
67     HKEY key = get_key(&path);
68
69     if (
70         key != 0
71         && ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key)
72     )
73     {
74         DWORD  type;
75         BYTE   data[MAX_REGISTRY_DATA_LENGTH];
76         DWORD  len = sizeof(data);
77         LIST const* const field = lol_get(frame->args, 1);
78
79         if ( ERROR_SUCCESS ==
80              RegQueryValueEx(key, field ? field->string : 0, 0, &type, data, &len) )
81         {
82             switch (type)
83             {
84
85              case REG_EXPAND_SZ:
86                  {
87                      long len;
88                      string expanded[1];
89                      string_new(expanded);
90
91                      while (
92                          (len = ExpandEnvironmentStrings(
93                              (LPCSTR)data, expanded->value, expanded->capacity))
94                          > expanded->capacity
95                      )
96                          string_reserve(expanded, len);
97
98                      expanded->size = len - 1;
99
100                      result = list_new( result, newstr(expanded->value) );
101                      string_free( expanded );
102                  }
103                  break;
104
105              case REG_MULTI_SZ:
106                  {
107                      char* s;
108
109                      for (s = (char*)data; *s; s += strlen(s) + 1)
110                          result = list_new( result, newstr(s) );
111
112                  }
113                  break;
114
115              case REG_DWORD:
116                  {
117                      char buf[100];
118                      sprintf( buf, "%u", *(PDWORD)data );
119                      result = list_new( result, newstr(buf) );
120                  }
121                  break;
122
123              case REG_SZ:
124                  result = list_new( result, newstr((char*)data) );
125                  break;
126             }
127         }
128         RegCloseKey(key);
129     }
130     return  result;
131 }
132
133 static LIST* get_subkey_names(HKEY key, char const* path)
134 {
135     LIST* result = 0;
136
137     if ( ERROR_SUCCESS ==
138          RegOpenKeyEx(key, path, 0, KEY_ENUMERATE_SUB_KEYS, &key)
139     )
140     {
141         char name[MAX_REGISTRY_KEYNAME_LENGTH];
142         DWORD name_size = sizeof(name);
143         DWORD index;
144         FILETIME last_write_time;
145
146         for ( index = 0;
147               ERROR_SUCCESS == RegEnumKeyEx(
148                   key, index, name, &name_size, 0, 0, 0, &last_write_time);
149               ++index,
150               name_size = sizeof(name)
151         )
152         {
153             name[name_size] = 0;
154             result = list_append(result, list_new(0, newstr(name)));
155         }
156
157         RegCloseKey(key);
158     }
159
160     return result;
161 }
162
163 static LIST* get_value_names(HKEY key, char const* path)
164 {
165     LIST* result = 0;
166
167     if ( ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key) )
168     {
169         char name[MAX_REGISTRY_VALUENAME_LENGTH];
170         DWORD name_size = sizeof(name);
171         DWORD index;
172
173         for ( index = 0;
174               ERROR_SUCCESS == RegEnumValue(
175                   key, index, name, &name_size, 0, 0, 0, 0);
176               ++index,
177               name_size = sizeof(name)
178         )
179         {
180             name[name_size] = 0;
181             result = list_append(result, list_new(0, newstr(name)));
182         }
183
184         RegCloseKey(key);
185     }
186
187     return result;
188 }
189
190 LIST*
191 builtin_system_registry_names(
192     PARSE    *parse,
193     FRAME    *frame )
194 {
195     char const* path        = lol_get(frame->args, 0)->string;
196     char const* result_type = lol_get(frame->args, 1)->string;
197
198     HKEY key = get_key(&path);
199
200     if ( !strcmp(result_type, "subkeys") )
201         return get_subkey_names(key, path);
202     if ( !strcmp(result_type, "values") )
203         return get_value_names(key, path);
204     return 0;
205 }
206
207 # endif