changeset 675:4ad764bfb39c

Add writing of the NSS line into the registry
author Andre Heinecke <andre.heinecke@intevation.de>
date Fri, 27 Jun 2014 18:53:52 +0200
parents f1795a232418
children cb40af11ec3a
files cinst/nssstore_win.c common/util.c common/util.h
diffstat 3 files changed, 161 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/cinst/nssstore_win.c	Fri Jun 27 16:18:10 2014 +0200
+++ b/cinst/nssstore_win.c	Fri Jun 27 18:53:52 2014 +0200
@@ -56,6 +56,9 @@
 #define APPNAME L"cinst"
 #endif
 
+/**@def The name of the nss installation process */
+#define NSS_APP_NAME L"mozilla.exe"
+
 #ifndef SELECTION_FILE_NAME
 #define SELECTION_FILE_NAME L"currently_selected.txt"
 #endif
@@ -358,6 +361,8 @@
       goto done;
     }
 
+  error = false;
+
 done:
   xfree (current_user);
 
@@ -377,6 +382,53 @@
   return retval;
 }
 
+/** @brief Build the command line for the NSS installation process
+  *
+  * Caller has to free the return value
+  *
+  * @param [in] selection_file the certificates to install
+  *
+  * @returns the command line to install the certificates. */
+static wchar_t*
+get_command_line(wchar_t *selection_file)
+{
+  LPWSTR retval;
+  char *install_dir = get_install_dir();
+  wchar_t *w_inst_dir;
+  size_t cmd_line_len = 0;
+
+  if (install_dir == NULL)
+    {
+      ERRORPRINTF ("Failed to get installation directory");
+      return NULL;
+    }
+
+  w_inst_dir = utf8_to_wchar (install_dir, strlen(install_dir));
+  xfree (install_dir);
+
+  if (w_inst_dir == NULL)
+    {
+      ERRORPRINTF ("Failed to convert installation directory");
+      return NULL;
+    }
+
+  /* installdir + dirsep +  quotes + process name + space + quotes + selection_file
+     + NULL */
+  cmd_line_len = wcslen (w_inst_dir) + 1 + 2 + wcslen (NSS_APP_NAME) +
+    + 1 + 2 + wcslen(selection_file) + 1;
+  retval = xmalloc (cmd_line_len * sizeof(wchar_t));
+
+  wcscpy_s (retval, cmd_line_len, L"\"");
+  wcscat_s (retval, cmd_line_len, w_inst_dir);
+  wcscat_s (retval, cmd_line_len, L"\\");
+  wcscat_s (retval, cmd_line_len, NSS_APP_NAME);
+  wcscat_s (retval, cmd_line_len, L"\" \"");
+  wcscat_s (retval, cmd_line_len, selection_file);
+  wcscat_s (retval, cmd_line_len, L"\"");
+
+  return retval;
+}
+
 /**@brief Register NSS process as runOnce for other users
 *
 * Loads the registry hives of other users on the system and
@@ -396,9 +448,66 @@
 register_proccesses_for_others (wchar_t *selection_file)
 {
   char **hives = locate_other_hives();
+  int i = 0;
+  wchar_t *run_command = NULL;
 
+  if (hives == NULL)
+    {
+      DEBUGPRINTF ("No hives found.");
+      return;
+    }
+  run_command = get_command_line (selection_file);
+  for (i = 0; hives[i] != NULL; i++)
+    {
+      LONG ret = 0;
+      wchar_t *hivepath = utf8_to_wchar (hives[i], strlen(hives[i]));
+      HKEY key_handle = NULL;
+
+      if (hivepath == NULL)
+        {
+          ERRORPRINTF ("Failed to read hive path");
+          continue;
+        }
+      ret = RegLoadKeyW (HKEY_LOCAL_MACHINE, APPNAME L"_tmphive", hivepath);
+
+      xfree (hivepath);
+      hivepath = NULL;
+
+      if (ret != ERROR_SUCCESS)
+        {
+          /* This is somewhat expected if the registry is not located
+             in the standard location. Failure is accepted in that case. */
+          PRINTLASTERROR ("Failed to load hive.");
+          continue;
+        }
+
+      ret = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
+                           APPNAME L"_tmphive\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
+                           0,
+                           KEY_WRITE,
+                           &key_handle);
+
+      if (ret != ERROR_SUCCESS)
+        {
+          ERRORPRINTF ("Failed to find RunOnce key in other registry.");
+          RegUnLoadKey (HKEY_LOCAL_MACHINE, APPNAME L"_tmphive");
+          continue;
+        }
+
+      ret = RegSetValueExW (key_handle, APPNAME, 0, REG_SZ, (LPBYTE) run_command,
+                            (wcslen(run_command) + 1) * sizeof(wchar_t));
+
+      if (ret != ERROR_SUCCESS)
+        {
+          ERRORPRINTF ("Failed to write RunOnce key.");
+        }
+
+      RegCloseKey (key_handle);
+      RegUnLoadKey (HKEY_LOCAL_MACHINE, APPNAME L"_tmphive");
+    }
+
+  xfree (run_command);
   strv_free (hives);
-  printf("Selection file %S", selection_file);
 }
 
 /**@brief Start the process to install / remove
@@ -421,7 +530,6 @@
   PROCESS_INFORMATION piProcInfo = {0};
   STARTUPINFOW siStartInfo = {0};
   BOOL success = FALSE;
-  size_t cmd_line_len = 0;
 
   if (!selection_file)
     {
@@ -441,12 +549,13 @@
      restrict token -> hChildToken
   */
 
-  cmd_line_len = wcslen (lpApplicationName) + wcslen(selection_file) + 2;
-  lpCommandLine = xmalloc (cmd_line_len * sizeof(wchar_t));
+  lpCommandLine = get_command_line (selection_file);
 
-  wcscpy_s (lpCommandLine, cmd_line_len, lpApplicationName);
-  wcscpy_s (lpCommandLine, cmd_line_len, L" ");
-  wcscat_s (lpCommandLine, cmd_line_len, selection_file);
+  if (lpCommandLine == NULL)
+    {
+      ERRORPRINTF ("Failed to build command line.");
+      return false;
+    }
 
   DEBUGPRINTF ("Starting %S with command line %S\n", lpApplicationName, lpCommandLine);
 
--- a/common/util.c	Fri Jun 27 16:18:10 2014 +0200
+++ b/common/util.c	Fri Jun 27 18:53:52 2014 +0200
@@ -20,6 +20,40 @@
 #endif
 
 #ifdef WIN32
+char * get_install_dir()
+{
+  wchar_t wPath[MAX_PATH];
+  char *utf8path = NULL;
+  char *dirsep = NULL;
+
+  if (!GetModuleFileNameW (NULL, wPath, MAX_PATH - 1)) 
+    {
+      PRINTLASTERROR ("Failed to obtain module file name. Path too long?");
+      return NULL;
+    }
+
+  /* wPath might not be 0 terminated */
+  wPath[MAX_PATH - 1] = '\0';
+
+  utf8path = wchar_to_utf8 (wPath, wcsnlen(wPath, MAX_PATH));
+
+  if (utf8path == NULL)
+    {
+      ERRORPRINTF ("Failed to convert module path to utf-8");
+      return NULL;
+    }
+
+  /* Cut away the executable name */
+  dirsep = strrchr(utf8path, '\\');
+  if (dirsep == NULL)
+    {
+      ERRORPRINTF ("Failed to find directory seperator.");
+      return NULL;
+    }
+  *dirsep = '\0';
+  return utf8path;
+}
+
 static PSID
 copy_sid(PSID from)
 {
--- a/common/util.h	Fri Jun 27 16:18:10 2014 +0200
+++ b/common/util.h	Fri Jun 27 18:53:52 2014 +0200
@@ -51,6 +51,17 @@
  * @returns A copy of the process owners sid or NULL on error.
  */
 PSID get_process_owner(HANDLE hProcess);
+
+/**@brief Get the directory in which the current process resides in
+ *
+ * Look up the directory in which the current process is placed.
+ * If the path is longer then MAX_PATH NULL is returned.
+ *
+ * Returns a utf-8 encoded string that has to be freed by the caller
+ *
+ * @returns The directory of the current process
+ */
+char * get_install_dir();
 #endif
 
 #ifdef __cplusplus

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