diff 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
line wrap: on
line diff
--- a/cinst/nssstore_win.c	Fri Jun 27 11:51:53 2014 +0200
+++ b/cinst/nssstore_win.c	Fri Jun 27 16:18:10 2014 +0200
@@ -139,6 +139,113 @@
   return true;
 }
 
+/**@brief Read (and expand if necessary) a registry string.
+ *
+ * Reads a registry string and calls ExpandEnvironmentString
+ * if necessary on it. Returns a newly allocated string array
+ * with the expanded registry value converted to UTF-8
+ *
+ * Caller has to free return value with free.
+ *
+ * @param [in] root the root key (e.g. HKEY_LOCAL_MACHINE)
+ * @param [in] key the key
+ * @param [in] name the name of the value to read.
+ *
+ * @returns the expanded, null terminated utf-8 string of the value.
+ *          or NULL on error.
+ */
+static char*
+read_registry_string (const HKEY root, const wchar_t *key,
+                      const wchar_t *name)
+{
+  HKEY key_handle = NULL;
+  DWORD size = 0,
+        type = 0,
+        ex_size = 0,
+        dwRet = 0;
+  LONG ret = 0;
+  char *retval = NULL;
+  wchar_t *buf = NULL,
+          *ex_buf = NULL;
+  if (root == NULL || key == NULL || name == NULL)
+    {
+      ERRORPRINTF ("Invalid call to read_registry_string");
+      return NULL;
+    }
+
+  ret = RegOpenKeyExW (root, key, 0, KEY_READ, &key_handle);
+  if (ret != ERROR_SUCCESS)
+    {
+      ERRORPRINTF ("Failed to open key.");
+      return NULL;
+    }
+
+  /* Get the size */
+  ret = RegQueryValueExW (key_handle, name, 0, NULL, NULL, &size);
+  if (ret != ERROR_MORE_DATA && !(ret == ERROR_SUCCESS && size != 0))
+    {
+      ERRORPRINTF ("Failed to get required registry size.");
+      return retval;
+    }
+
+  /* Size is size in bytes not in characters */
+  buf = xmalloc (size + sizeof(wchar_t));
+
+  /* If the stored value is not zero terminated the returned value also
+     is not zero terminated. That's why we reserve more and ensure it's
+     initialized. */
+  memset (buf, 0, size + sizeof(wchar_t));
+
+  ret = RegQueryValueExW (key_handle, name, 0, &type, (LPBYTE) buf, &size);
+  if (ret != ERROR_SUCCESS)
+    {
+      ERRORPRINTF ("Failed get registry value.");
+      return retval;
+    }
+
+  if (type == REG_SZ || (type == REG_EXPAND_SZ && wcschr (buf, '%') == NULL))
+    {
+      /* Nothing to expand, we are done */
+      retval = wchar_to_utf8 (buf, wcslen (buf));
+      goto done;
+    }
+
+  if (type != REG_EXPAND_SZ)
+    {
+      ERRORPRINTF ("Unhandled registry type %i", type);
+      goto done;
+    }
+
+  /* Expand the registry string */
+  ex_size = ExpandEnvironmentStringsW (buf, NULL, 0);
+
+  if (ex_size == 0)
+    {
+      PRINTLASTERROR ("Failed to determine expanded environment size.");
+      goto done;
+    }
+
+  ex_buf = xmalloc ((ex_size + 1) * sizeof(wchar_t));
+
+  dwRet = ExpandEnvironmentStringsW (buf, ex_buf, ex_size);
+
+  ex_buf[ex_size] = '\0'; /* Make sure it's a string */
+
+  if (dwRet == 0 || dwRet != ex_size)
+    {
+      PRINTLASTERROR ("Failed to expand environment variables.");
+      goto done;
+    }
+
+  retval = wchar_to_utf8 (ex_buf, ex_size);
+
+done:
+  xfree (ex_buf);
+  xfree (buf);
+
+  RegCloseKey (key_handle);
+  return retval;
+}
 /**@brief Get the path to all users default registry hive
  *
  * Enumerates the keys in #PROFILE_LIST and retuns a
@@ -152,7 +259,6 @@
  *
  * @returns a newly allocated strv of the paths to the registry hives or NULL
  */
-
 static char**
 locate_other_hives()
 {
@@ -198,6 +304,11 @@
                                key_name, &key_len,
                                NULL, NULL, NULL, NULL)) == ERROR_SUCCESS)
     {
+      char *profile_path = NULL;
+      wchar_t *key_path = NULL;
+      size_t key_path_len = 0,
+             profile_path_len = 0;
+
       if (key_len == 257)
         {
           ERRORPRINTF ("Registry key too long.");
@@ -215,7 +326,30 @@
           continue;
         }
 
+      key_path_len = key_len + wcslen(PROFILE_LIST L"\\") + 1;
+      key_path = xmalloc (key_path_len * sizeof (wchar_t));
+
+      wcscpy_s (key_path, key_path_len, PROFILE_LIST L"\\");
+      wcscat_s (key_path, key_path_len, key_name);
+      key_path[key_len - 1] = '\0';
+
       DEBUGPRINTF ("Key : %S", key_name);
+      profile_path = read_registry_string (HKEY_LOCAL_MACHINE,
+                                           key_path, L"ProfileImagePath");
+      xfree (key_path);
+
+      if (profile_path == NULL)
+        {
+          ERRORPRINTF ("Failed to get profile path.");
+          continue;
+        }
+      profile_path_len = strlen (profile_path);
+      str_append_str (&profile_path, &profile_path_len, "\\ntuser.dat", 11);
+
+      strv_append (&retval, profile_path, profile_path_len);
+      DEBUGPRINTF ("Trying to access registry hive: %s", profile_path);
+
+      xfree (profile_path);
     }
 
   if (ret != ERROR_NO_MORE_ITEMS)

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