Index: ext/etc/etc.c
===================================================================
RCS file: /cvs/ruby/src/ruby/ext/etc/etc.c,v
retrieving revision 1.18
diff -U2 -p -r1.18 etc.c
--- ext/etc/etc.c	6 Sep 2005 23:35:15 -0000	1.18
+++ ext/etc/etc.c	7 Sep 2005 01:39:24 -0000
@@ -18,4 +18,5 @@
 #ifdef HAVE_GETPWENT
 #include <pwd.h>
+#define NEED_SETUP_PASSWD 1
 #endif
 
@@ -28,4 +29,54 @@
 #endif
 
+#if defined(_WIN32)
+#if !defined(NEED_SETUP_PASSWD) && defined(HAVE_LM_H)
+#include <lm.h>
+#define HAVE_ST_PW_GECOS 1
+#define HAVE_ST_PW_COMMENT 1
+struct passwd {
+    char *pw_name;
+    char *pw_passwd;
+    int pw_uid;
+    int pw_gid;
+    char *pw_gecos;
+    char *pw_dir;
+    char *pw_shell;
+    char *pw_comment;
+};
+
+typedef NET_API_STATUS (NET_API_FUNCTION *NetUserGetInfo_t)(LPCWSTR, LPCWSTR, DWORD, LPBYTE *);
+typedef NET_API_STATUS (NET_API_FUNCTION *NetApiBufferFree_t)(void *);
+
+static HANDLE netapi;
+static NetUserGetInfo_t getinfo;
+static NetApiBufferFree_t netfree;
+
+static int
+init_netapi()
+{
+    if (netapi == INVALID_HANDLE_VALUE) return 0;
+    if (netapi) return 1;
+    if (!(netapi = LoadLibrary("netapi32"))) {
+	netapi = INVALID_HANDLE_VALUE;
+	return 0;
+    }
+    getinfo = (NetUserGetInfo_t)GetProcAddress(netapi, "NetUserGetInfo");
+    netfree = (NetApiBufferFree_t)GetProcAddress(netapi, "NetApiBufferFree");
+    if (!getinfo || !netfree) {
+	FreeLibrary(netapi);
+	netapi = INVALID_HANDLE_VALUE;
+	return 0;
+    }
+#if 0
+    if (!getinfo) getinfo = (NetUserGetInfo_t)rb_notimplement;
+    if (!netfree) netfree = (NetApiBufferFree_t)rb_notimplement;
+#endif
+    return 1;
+}
+#endif
+
+#define NEED_SETUP_PASSWD 1
+#endif
+
 static VALUE sPasswd, sGroup;
 
@@ -54,5 +105,5 @@ etc_getlogin(obj)
 }
 
-#if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
+#if defined(NEED_SETUP_PASSWD) || defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
 static VALUE
 safe_setup_str(str)
@@ -64,5 +115,5 @@ safe_setup_str(str)
 #endif
 
-#ifdef HAVE_GETPWENT
+#ifdef NEED_SETUP_PASSWD
 static VALUE
 setup_passwd(pwd)
@@ -142,5 +193,74 @@ etc_getpwnam(obj, nam)
     if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %s", RSTRING(nam)->ptr);
     return setup_passwd(pwd);
-#else 
+#elif defined(_WIN32)
+    const DWORD w2mflag = WC_DISCARDNS|WC_SEPCHARS|WC_DEFAULTCHAR|WC_COMPOSITECHECK;
+#define WS2MB(ws, wl, mb, ml) \
+    WideCharToMultiByte(CP_OEMCP, w2mflag, ws, wl, mb, ml, NULL, NULL)
+#define MB2WS(mb, ml, ws, wl) \
+    MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, mb, ml, ws, wl)
+
+    void *ptr = NULL;
+    char* cname = StringValueCStr(nam);
+    int len = strlen(cname) + 1, wlen;
+    wchar_t *wname;
+    struct passwd pwd;
+
+    pwd.pw_name = cname;
+    pwd.pw_passwd = "*";
+    pwd.pw_uid = 0;
+    pwd.pw_gid = 0;
+    pwd.pw_dir = "";
+    pwd.pw_shell = "";
+    pwd.pw_comment = "";
+
+#if defined(HAVE_LM_H)
+    if (init_netapi()) {
+#define COPY2PWD(w, s) (						\
+	    len = WS2MB(buf->w, wlen = lstrlenW(buf->w), NULL, 0),	\
+	    pwd.s = ALLOCA_N(char, len + 1),				\
+	    pwd.s[WS2MB(buf->w, wlen, pwd.s, len)] = 0,			\
+	    (void)0)
+
+	wlen = MB2WS(cname, len, NULL, 0);
+	wname = ALLOCA_N(wchar_t, wlen);
+	if (!MB2WS(cname, len, wname, wlen)) {
+	    rb_raise(rb_eArgError, "invalid user name - %s", cname);
+	}
+	if (getinfo(NULL, wname, 3, (LPBYTE *)&ptr) == NERR_Success) {
+	    LPUSER_INFO_3 buf = ptr;
+	    COPY2PWD(usri3_password, pw_passwd);
+	    COPY2PWD(usri3_home_dir, pw_dir);
+	    COPY2PWD(usri3_comment, pw_comment);
+	    COPY2PWD(usri3_full_name, pw_gecos);
+	    pwd.pw_uid = buf->usri3_user_id;
+	    pwd.pw_gid = buf->usri3_primary_group_id;
+	}
+	else if (getinfo(NULL, wname, 2, (LPBYTE *)&ptr) == NERR_Success) {
+	    LPUSER_INFO_2 buf = ptr;
+	    COPY2PWD(usri2_comment, pw_comment);
+	}
+	else {
+	    rb_raise(rb_eArgError, "can't find user for %s", cname);
+	}
+	if (ptr) {
+	    netfree(ptr);
+	}
+    }
+#endif
+
+    if (!(cname = getenv("RUBYSHELL")) && !(cname = getenv("COMSPEC"))) {
+	OSVERSIONINFO osver;
+	memset(&osver, 0, sizeof(OSVERSIONINFO));
+	osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+	GetVersionEx(&osver);
+	if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+	    cname = "command.com";
+	else
+	    cname = "cmd.exe";
+    }
+    pwd.pw_shell = cname;
+
+    return setup_passwd(&pwd);
+#else
     return Qnil;
 #endif
Index: ext/etc/extconf.rb
===================================================================
RCS file: /cvs/ruby/src/ruby/ext/etc/extconf.rb,v
retrieving revision 1.6
diff -U2 -p -r1.6 extconf.rb
--- ext/etc/extconf.rb	6 Sep 2005 23:35:15 -0000	1.6
+++ ext/etc/extconf.rb	7 Sep 2005 01:39:24 -0000
@@ -25,4 +25,6 @@ if  a or b or c
   have_struct_member('struct passwd', 'pw_passwd', 'pwd.h')
   have_struct_member('struct group', 'gr_passwd', 'grp.h')
+  have_header("lm.h") and have_library("netapi32")
+  have_header("lastlog.h") and have_header("paths.h")
   have_type("uid_t");
   create_makefile("etc")
