[Patch] Loading the registry hive on Win9x

Pierre A. Humblet pierre@phumblet.no-ip.org
Tue Nov 16 02:26:00 GMT 2004


This patch is the first of two to also load the registry hive on
Win9x during seteuid, and to apply the method recommended in
MS KB 199190 to avoid using HKCU.
 
This will yield the correct user mounts under ssh, telnet, etc...

Using the new method cygheap_user::get_windows_id() also streamlines
some aspects of Cygwin, e.g. in shared.cc below and more tomorrow.

Pierre

2004-11-16  Pierre Humblet <pierre.humblet@ieee.org>

	* cygheap.h (cygheap_user::get_windows_id): New method.
	* registry.h (get_registry_hive_path): Change argument type.
	(load_registry_hive): Ditto.
	* registry.cc (get_registry_hive_path): Change argument type and take
	Win9x keys into account.
	(load_registry_hive): Ditto.
	* uinfo.cc (cygheap_user::env_userprofile): Use get_windows_id, even
	for SYSTEM.
	* shared.cc (user_shared_initialize): Use get_windows_id.
	* syscalls.cc (seteuid32): Load the registry hive and reload the user
	shared also on Win9x.
-------------- next part --------------
Index: cygheap.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/cygheap.h,v
retrieving revision 1.91
diff -u -p -r1.91 cygheap.h
--- cygheap.h	28 Oct 2004 01:46:01 -0000	1.91
+++ cygheap.h	16 Nov 2004 01:42:18 -0000
@@ -206,6 +206,14 @@ public:
 	internal_token = NO_IMPERSONATION;
       }
   }
+  char * get_windows_id (char * buf)
+  {
+    if (wincap.is_winnt ())
+      return effec_cygsid.string (buf);
+    else
+      return strcpy (buf, name ());
+  }
+
   const char *cygheap_user::test_uid (char *&, const char *, size_t)
     __attribute__ ((regparm (3)));
 };
Index: registry.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/registry.h,v
retrieving revision 1.3
diff -u -p -r1.3 registry.h
--- registry.h	11 Sep 2001 20:01:00 -0000	1.3
+++ registry.h	16 Nov 2004 01:42:18 -0000
@@ -39,5 +39,5 @@ public:
 };

 /* Evaluates path to the directory of the local user registry hive */
-char *__stdcall get_registry_hive_path (const PSID psid, char *path);
-void __stdcall load_registry_hive (PSID psid);
+char *__stdcall get_registry_hive_path (const char *name, char *path);
+void __stdcall load_registry_hive (const char *name);
Index: registry.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/registry.cc,v
retrieving revision 1.20
diff -u -p -r1.20 registry.cc
--- registry.cc	26 Oct 2004 01:53:27 -0000	1.20
+++ registry.cc	16 Nov 2004 01:42:18 -0000
@@ -194,18 +194,16 @@ reg_key::~reg_key ()
 }

 char *
-get_registry_hive_path (const PSID psid, char *path)
+get_registry_hive_path (const char *name, char *path)
 {
-  char sid[256];
   char key[256];
   HKEY hkey;

-  if (!psid || !path)
+  if (!name || !path)
     return NULL;
-  cygpsid csid (psid);
-  csid.string (sid);
-  strcpy (key,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
-  strcat (key, sid);
+  __small_sprintf (key, "SOFTWARE\\Microsoft\\Windows%s\\CurrentVersion\\ProfileList\\",
+		   wincap.is_winnt ()?" NT":"");
+  strcat (key, name);
   if (!RegOpenKeyExA (HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hkey))
     {
       char buf[256];
@@ -224,31 +222,31 @@ get_registry_hive_path (const PSID psid,
 }

 void
-load_registry_hive (PSID psid)
+load_registry_hive (const char * name)
 {
-  char sid[256];
   char path[CYG_MAX_PATH + 1];
   HKEY hkey;
   LONG ret;

-  if (!psid)
+  if (!name)
     return;
   /* Check if user hive is already loaded. */
-  cygpsid csid (psid);
-  csid.string (sid);
-  if (!RegOpenKeyExA (HKEY_USERS, sid, 0, KEY_READ, &hkey))
+  if (!RegOpenKeyExA (HKEY_USERS, name, 0, KEY_READ, &hkey))
     {
-      debug_printf ("User registry hive for %s already exists", sid);
+      debug_printf ("User registry hive for %s already exists", name);
       RegCloseKey (hkey);
       return;
     }
   /* This is only called while deimpersonated */
   set_process_privilege (SE_RESTORE_NAME);
-  if (get_registry_hive_path (psid, path))
+  if (get_registry_hive_path (name, path))
     {
-      strcat (path, "\\NTUSER.DAT");
-      if ((ret = RegLoadKeyA (HKEY_USERS, sid, path)) != ERROR_SUCCESS)
-	debug_printf ("Loading user registry hive for %s failed: %d", sid, ret);
+      if (wincap.is_winnt ())
+	strcat (path, "\\NTUSER.DAT");
+      else
+	strcat (path, "\\USER.DAT");
+      if ((ret = RegLoadKeyA (HKEY_USERS, name, path)) != ERROR_SUCCESS)
+	debug_printf ("Loading user registry hive for %s failed: %d", name, ret);
     }
 }

Index: uinfo.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/uinfo.cc,v
retrieving revision 1.132
diff -u -p -r1.132 uinfo.cc
--- uinfo.cc	28 Oct 2004 01:46:01 -0000	1.132
+++ uinfo.cc	16 Nov 2004 01:42:19 -0000
@@ -419,11 +419,10 @@ cygheap_user::env_userprofile (const cha
     return puserprof;

   char userprofile_env_buf[CYG_MAX_PATH + 1];
+  char win_id[UNLEN + 1]; /* Large enough for SID */
+
   cfree_and_set (puserprof, almost_null);
-  /* FIXME: Should this just be setting a puserprofile like everything else? */
-  const char *myname = winname ();
-  if (myname && strcasematch (myname, "SYSTEM")
-      && get_registry_hive_path (sid (), userprofile_env_buf))
+  if (get_registry_hive_path (get_windows_id (win_id), userprofile_env_buf))
     puserprof = cstrdup (userprofile_env_buf);

   return puserprof;
Index: shared.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/shared.cc,v
retrieving revision 1.82
diff -u -p -r1.82 shared.cc
--- shared.cc	28 May 2004 19:50:06 -0000	1.82
+++ shared.cc	16 Nov 2004 01:42:19 -0000
@@ -161,16 +161,8 @@ user_shared_initialize (bool reinit)
     }

   if (!cygwin_user_h)
-    {
-      if (wincap.has_security ())
-	{
-	  cygpsid tu (cygheap->user.sid ());
-	  tu.string (name);
-	}
-      else
-	strcpy (name, cygheap->user.name ());
-    }
+    cygheap->user.get_windows_id (name);

   user_shared = (user_info *) open_shared (name, USER_VERSION,
 					    cygwin_user_h, sizeof (user_info),
Index: syscalls.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.349
diff -u -p -r1.349 syscalls.cc
--- syscalls.cc	28 Oct 2004 01:46:01 -0000	1.349
+++ syscalls.cc	16 Nov 2004 01:42:23 -0000
@@ -2008,13 +2008,16 @@ seteuid32 (__uid32_t uid)
   user_groups &groups = cygheap->user.groups;
   HANDLE ptok, new_token = INVALID_HANDLE_VALUE;
   struct passwd * pw_new;
-  bool token_is_internal, issamesid;
+  bool token_is_internal, issamesid = false;
   char dacl_buf[MAX_DACL_LEN (5)];
   TOKEN_DEFAULT_DACL tdacl = {};

   pw_new = internal_getpwuid (uid);
   if (!wincap.has_security () && pw_new)
+    {
+      load_registry_hive (pw_new->pw_name);
     goto success_9x;
+    }
   if (!usersid.getfrompw (pw_new))
     {
       set_errno (EINVAL);
@@ -2082,7 +2085,8 @@ seteuid32 (__uid32_t uid)
   if (new_token != ptok)
     {
       /* Avoid having HKCU use default user */
-      load_registry_hive (usersid);
+      char name[128];
+      load_registry_hive (usersid.string (name));

       /* Try setting owner to same value as user. */
       if (!SetTokenInformation (new_token, TokenOwner,
@@ -2106,16 +2110,17 @@ seteuid32 (__uid32_t uid)
   cygheap->user.set_sid (usersid);
   cygheap->user.current_token = new_token == ptok ? NO_IMPERSONATION
 						  : new_token;
-  if (!issamesid) /* MS KB 199190 */
-    RegCloseKey (HKEY_CURRENT_USER);
   cygheap->user.reimpersonate ();
-  if (!issamesid)
-    user_shared_initialize (true);

 success_9x:
   cygheap->user.set_name (pw_new->pw_name);
   myself->uid = uid;
   groups.ischanged = FALSE;
+  if (!issamesid) /* MS KB 199190 */
+    {
+      RegCloseKey (HKEY_CURRENT_USER);
+      user_shared_initialize (true);
+    }
   return 0;

 failed:


More information about the Cygwin-patches mailing list