comparison cinst/nssstore_win.c @ 674:f1795a232418

Implement reading registry entries for other users.
author Andre Heinecke <andre.heinecke@intevation.de>
date Fri, 27 Jun 2014 16:18:10 +0200
parents d4766b4922c9
children 4ad764bfb39c
comparison
equal deleted inserted replaced
673:e8bc1215904e 674:f1795a232418
137 } 137 }
138 } 138 }
139 return true; 139 return true;
140 } 140 }
141 141
142 /**@brief Read (and expand if necessary) a registry string.
143 *
144 * Reads a registry string and calls ExpandEnvironmentString
145 * if necessary on it. Returns a newly allocated string array
146 * with the expanded registry value converted to UTF-8
147 *
148 * Caller has to free return value with free.
149 *
150 * @param [in] root the root key (e.g. HKEY_LOCAL_MACHINE)
151 * @param [in] key the key
152 * @param [in] name the name of the value to read.
153 *
154 * @returns the expanded, null terminated utf-8 string of the value.
155 * or NULL on error.
156 */
157 static char*
158 read_registry_string (const HKEY root, const wchar_t *key,
159 const wchar_t *name)
160 {
161 HKEY key_handle = NULL;
162 DWORD size = 0,
163 type = 0,
164 ex_size = 0,
165 dwRet = 0;
166 LONG ret = 0;
167 char *retval = NULL;
168 wchar_t *buf = NULL,
169 *ex_buf = NULL;
170 if (root == NULL || key == NULL || name == NULL)
171 {
172 ERRORPRINTF ("Invalid call to read_registry_string");
173 return NULL;
174 }
175
176 ret = RegOpenKeyExW (root, key, 0, KEY_READ, &key_handle);
177 if (ret != ERROR_SUCCESS)
178 {
179 ERRORPRINTF ("Failed to open key.");
180 return NULL;
181 }
182
183 /* Get the size */
184 ret = RegQueryValueExW (key_handle, name, 0, NULL, NULL, &size);
185 if (ret != ERROR_MORE_DATA && !(ret == ERROR_SUCCESS && size != 0))
186 {
187 ERRORPRINTF ("Failed to get required registry size.");
188 return retval;
189 }
190
191 /* Size is size in bytes not in characters */
192 buf = xmalloc (size + sizeof(wchar_t));
193
194 /* If the stored value is not zero terminated the returned value also
195 is not zero terminated. That's why we reserve more and ensure it's
196 initialized. */
197 memset (buf, 0, size + sizeof(wchar_t));
198
199 ret = RegQueryValueExW (key_handle, name, 0, &type, (LPBYTE) buf, &size);
200 if (ret != ERROR_SUCCESS)
201 {
202 ERRORPRINTF ("Failed get registry value.");
203 return retval;
204 }
205
206 if (type == REG_SZ || (type == REG_EXPAND_SZ && wcschr (buf, '%') == NULL))
207 {
208 /* Nothing to expand, we are done */
209 retval = wchar_to_utf8 (buf, wcslen (buf));
210 goto done;
211 }
212
213 if (type != REG_EXPAND_SZ)
214 {
215 ERRORPRINTF ("Unhandled registry type %i", type);
216 goto done;
217 }
218
219 /* Expand the registry string */
220 ex_size = ExpandEnvironmentStringsW (buf, NULL, 0);
221
222 if (ex_size == 0)
223 {
224 PRINTLASTERROR ("Failed to determine expanded environment size.");
225 goto done;
226 }
227
228 ex_buf = xmalloc ((ex_size + 1) * sizeof(wchar_t));
229
230 dwRet = ExpandEnvironmentStringsW (buf, ex_buf, ex_size);
231
232 ex_buf[ex_size] = '\0'; /* Make sure it's a string */
233
234 if (dwRet == 0 || dwRet != ex_size)
235 {
236 PRINTLASTERROR ("Failed to expand environment variables.");
237 goto done;
238 }
239
240 retval = wchar_to_utf8 (ex_buf, ex_size);
241
242 done:
243 xfree (ex_buf);
244 xfree (buf);
245
246 RegCloseKey (key_handle);
247 return retval;
248 }
142 /**@brief Get the path to all users default registry hive 249 /**@brief Get the path to all users default registry hive
143 * 250 *
144 * Enumerates the keys in #PROFILE_LIST and retuns a 251 * Enumerates the keys in #PROFILE_LIST and retuns a
145 * strv array with the utf-8 encoded paths to their suggested 252 * strv array with the utf-8 encoded paths to their suggested
146 * registry hive location. 253 * registry hive location.
150 * 257 *
151 * Use strv_free to free that array. 258 * Use strv_free to free that array.
152 * 259 *
153 * @returns a newly allocated strv of the paths to the registry hives or NULL 260 * @returns a newly allocated strv of the paths to the registry hives or NULL
154 */ 261 */
155
156 static char** 262 static char**
157 locate_other_hives() 263 locate_other_hives()
158 { 264 {
159 HKEY profile_list = NULL; 265 HKEY profile_list = NULL;
160 int ret = 0; 266 int ret = 0;
196 302
197 while ((ret = RegEnumKeyExW (profile_list, index++, 303 while ((ret = RegEnumKeyExW (profile_list, index++,
198 key_name, &key_len, 304 key_name, &key_len,
199 NULL, NULL, NULL, NULL)) == ERROR_SUCCESS) 305 NULL, NULL, NULL, NULL)) == ERROR_SUCCESS)
200 { 306 {
307 char *profile_path = NULL;
308 wchar_t *key_path = NULL;
309 size_t key_path_len = 0,
310 profile_path_len = 0;
311
201 if (key_len == 257) 312 if (key_len == 257)
202 { 313 {
203 ERRORPRINTF ("Registry key too long."); 314 ERRORPRINTF ("Registry key too long.");
204 goto done; 315 goto done;
205 } 316 }
213 /* S-1-5-21 is the well known prefix for local users. Skip all 324 /* S-1-5-21 is the well known prefix for local users. Skip all
214 others and the current user*/ 325 others and the current user*/
215 continue; 326 continue;
216 } 327 }
217 328
329 key_path_len = key_len + wcslen(PROFILE_LIST L"\\") + 1;
330 key_path = xmalloc (key_path_len * sizeof (wchar_t));
331
332 wcscpy_s (key_path, key_path_len, PROFILE_LIST L"\\");
333 wcscat_s (key_path, key_path_len, key_name);
334 key_path[key_len - 1] = '\0';
335
218 DEBUGPRINTF ("Key : %S", key_name); 336 DEBUGPRINTF ("Key : %S", key_name);
337 profile_path = read_registry_string (HKEY_LOCAL_MACHINE,
338 key_path, L"ProfileImagePath");
339 xfree (key_path);
340
341 if (profile_path == NULL)
342 {
343 ERRORPRINTF ("Failed to get profile path.");
344 continue;
345 }
346 profile_path_len = strlen (profile_path);
347 str_append_str (&profile_path, &profile_path_len, "\\ntuser.dat", 11);
348
349 strv_append (&retval, profile_path, profile_path_len);
350 DEBUGPRINTF ("Trying to access registry hive: %s", profile_path);
351
352 xfree (profile_path);
219 } 353 }
220 354
221 if (ret != ERROR_NO_MORE_ITEMS) 355 if (ret != ERROR_NO_MORE_ITEMS)
222 { 356 {
223 ERRORPRINTF ("Failed to enumeratre profile list. Error: %i", ret); 357 ERRORPRINTF ("Failed to enumeratre profile list. Error: %i", ret);

http://wald.intevation.org/projects/trustbridge/