#define _ANONYMOUS_STRUCT
#endif
#include <windows.h>
+#include <lmcons.h>
#include <shlobj.h>
#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
extern int w32_num_mouse_buttons;
\f
-/*
- Initialization states
- */
+/* Initialization states.
+
+ WARNING: If you add any more such variables for additional APIs,
+ you MUST add initialization for them to globals_of_w32
+ below. This is because these variables might get set
+ to non-NULL values during dumping, but the dumped Emacs
+ cannot reuse those values, because it could be run on a
+ different version of the OS, where API addresses are
+ different. */
static BOOL g_b_init_is_windows_9x;
static BOOL g_b_init_open_process_token;
static BOOL g_b_init_get_token_information;
static BOOL g_b_init_lookup_account_sid;
static BOOL g_b_init_get_sid_identifier_authority;
+static BOOL g_b_init_get_sid_sub_authority;
+static BOOL g_b_init_get_sid_sub_authority_count;
/*
BEGIN: Wrapper functions around OpenProcessToken
LPVOID TokenInformation,
DWORD TokenInformationLength,
PDWORD ReturnLength);
+typedef BOOL (WINAPI * GetProcessTimes_Proc) (
+ HANDLE process_handle,
+ LPFILETIME creation_time,
+ LPFILETIME exit_time,
+ LPFILETIME kernel_time,
+ LPFILETIME user_time);
+
+GetProcessTimes_Proc get_process_times_fn = NULL;
+
#ifdef _UNICODE
const char * const LookupAccountSid_Name = "LookupAccountSidW";
#else
PSID_NAME_USE peUse);
typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
PSID pSid);
+typedef PDWORD (WINAPI * GetSidSubAuthority_Proc) (
+ PSID pSid,
+ DWORD n);
+typedef PUCHAR (WINAPI * GetSidSubAuthorityCount_Proc) (
+ PSID pSid);
+
/* ** A utility function ** */
static BOOL
return s_b_ret;
}
+/* Get total user and system times for get-internal-run-time.
+ Returns a list of three integers if the times are provided by the OS
+ (NT derivatives), otherwise it returns the result of current-time. */
+Lisp_Object
+w32_get_internal_run_time ()
+{
+ if (get_process_times_fn)
+ {
+ FILETIME create, exit, kernel, user;
+ HANDLE proc = GetCurrentProcess();
+ if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
+ {
+ LARGE_INTEGER user_int, kernel_int, total;
+ int microseconds;
+ user_int.LowPart = user.dwLowDateTime;
+ user_int.HighPart = user.dwHighDateTime;
+ kernel_int.LowPart = kernel.dwLowDateTime;
+ kernel_int.HighPart = kernel.dwHighDateTime;
+ total.QuadPart = user_int.QuadPart + kernel_int.QuadPart;
+ /* FILETIME is 100 nanosecond increments, Emacs only wants
+ microsecond resolution. */
+ total.QuadPart /= 10;
+ microseconds = total.QuadPart % 1000000;
+ total.QuadPart /= 1000000;
+
+ /* Sanity check to make sure we can represent the result. */
+ if (total.HighPart == 0)
+ {
+ int secs = total.LowPart;
+
+ return list3 (make_number ((secs >> 16) & 0xffff),
+ make_number (secs & 0xffff),
+ make_number (microseconds));
+ }
+ }
+ }
+
+ return Fcurrent_time ();
+}
+
/* ** The wrapper functions ** */
BOOL WINAPI open_process_token (
return (s_pfn_Get_Sid_Identifier_Authority (pSid));
}
+PDWORD WINAPI get_sid_sub_authority (
+ PSID pSid,
+ DWORD n)
+{
+ static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority = NULL;
+ static DWORD zero = 0U;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return &zero;
+ }
+ if (g_b_init_get_sid_sub_authority == 0)
+ {
+ g_b_init_get_sid_sub_authority = 1;
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ s_pfn_Get_Sid_Sub_Authority =
+ (GetSidSubAuthority_Proc) GetProcAddress (
+ hm_advapi32, "GetSidSubAuthority");
+ }
+ if (s_pfn_Get_Sid_Sub_Authority == NULL)
+ {
+ return &zero;
+ }
+ return (s_pfn_Get_Sid_Sub_Authority (pSid, n));
+}
+
+PUCHAR WINAPI get_sid_sub_authority_count (
+ PSID pSid)
+{
+ static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count = NULL;
+ static UCHAR zero = 0U;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return &zero;
+ }
+ if (g_b_init_get_sid_sub_authority_count == 0)
+ {
+ g_b_init_get_sid_sub_authority_count = 1;
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ s_pfn_Get_Sid_Sub_Authority_Count =
+ (GetSidSubAuthorityCount_Proc) GetProcAddress (
+ hm_advapi32, "GetSidSubAuthorityCount");
+ }
+ if (s_pfn_Get_Sid_Sub_Authority_Count == NULL)
+ {
+ return &zero;
+ }
+ return (s_pfn_Get_Sid_Sub_Authority_Count (pSid));
+}
+
/*
END: Wrapper functions around OpenProcessToken
and other functions in advapi32.dll that are only
the user-sid as the user id value (same for group id using the
primary group sid from the process token). */
- char user_sid[256], name[256], domain[256];
+ char name[UNLEN+1], domain[1025];
DWORD length = sizeof (name), dlength = sizeof (domain), trash;
HANDLE token = NULL;
SID_NAME_USE user_type;
+ unsigned char buf[1024];
+ TOKEN_USER user_token;
+ TOKEN_PRIMARY_GROUP group_token;
if (open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
&& get_token_information (token, TokenUser,
- (PVOID) user_sid, sizeof (user_sid), &trash)
- && lookup_account_sid (NULL, *((PSID *) user_sid), name, &length,
- domain, &dlength, &user_type))
+ (PVOID)buf, sizeof (buf), &trash)
+ && (memcpy (&user_token, buf, sizeof (user_token)),
+ lookup_account_sid (NULL, user_token.User.Sid, name, &length,
+ domain, &dlength, &user_type)))
{
strcpy (the_passwd.pw_name, name);
- /* Determine a reasonable uid value. */
+ /* Determine a reasonable uid value. */
if (stricmp ("administrator", name) == 0)
{
- the_passwd.pw_uid = 0;
- the_passwd.pw_gid = 0;
+ the_passwd.pw_uid = 500; /* well-known Administrator uid */
+ the_passwd.pw_gid = 513; /* well-known None gid */
}
else
{
- SID_IDENTIFIER_AUTHORITY * pSIA;
-
- pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
- /* I believe the relative portion is the last 4 bytes (of 6)
- with msb first. */
- the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
- (pSIA->Value[3] << 16) +
- (pSIA->Value[4] << 8) +
- (pSIA->Value[5] << 0));
- /* restrict to conventional uid range for normal users */
- the_passwd.pw_uid = the_passwd.pw_uid % 60001;
+ /* Use the last sub-authority value of the RID, the relative
+ portion of the SID, as user/group ID. */
+ DWORD n_subauthorities =
+ *get_sid_sub_authority_count (user_token.User.Sid);
+
+ if (n_subauthorities < 1)
+ the_passwd.pw_uid = 0; /* the "World" RID */
+ else
+ {
+ the_passwd.pw_uid =
+ *get_sid_sub_authority (user_token.User.Sid,
+ n_subauthorities - 1);
+ }
/* Get group id */
if (get_token_information (token, TokenPrimaryGroup,
- (PVOID) user_sid, sizeof (user_sid), &trash))
+ (PVOID)buf, sizeof (buf), &trash))
{
- SID_IDENTIFIER_AUTHORITY * pSIA;
-
- pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
- the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
- (pSIA->Value[3] << 16) +
- (pSIA->Value[4] << 8) +
- (pSIA->Value[5] << 0));
- /* I don't know if this is necessary, but for safety... */
- the_passwd.pw_gid = the_passwd.pw_gid % 60001;
+ memcpy (&group_token, buf, sizeof (group_token));
+ n_subauthorities =
+ *get_sid_sub_authority_count (group_token.PrimaryGroup);
+
+ if (n_subauthorities < 1)
+ the_passwd.pw_gid = 0; /* the "World" RID */
+ else
+ {
+ the_passwd.pw_gid =
+ *get_sid_sub_authority (group_token.PrimaryGroup,
+ n_subauthorities - 1);
+ }
}
else
the_passwd.pw_gid = the_passwd.pw_uid;
return 0;
}
-void
-unrequest_sigio (void)
-{
- return;
-}
-
-void
-request_sigio (void)
-{
- return;
-}
-
#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
LPBYTE
break;
#endif
-#ifdef PROCESSOR_INTEL_860
- case PROCESSOR_INTEL_860:
- arch = "i860";
- break;
-#endif
-
#ifdef PROCESSOR_MIPS_R2000
case PROCESSOR_MIPS_R2000:
case PROCESSOR_MIPS_R3000:
value returned by stat(). */
dir_static.d_ino = 1;
+ strcpy (dir_static.d_name, dir_find_data.cFileName);
+
+ /* If the file name in cFileName[] includes `?' characters, it means
+ the original file name used characters that cannot be represented
+ by the current ANSI codepage. To avoid total lossage, retrieve
+ the short 8+3 alias of the long file name. */
+ if (_mbspbrk (dir_static.d_name, "?"))
+ {
+ strcpy (dir_static.d_name, dir_find_data.cAlternateFileName);
+ downcase = 1; /* 8+3 aliases are returned in all caps */
+ }
+ dir_static.d_namlen = strlen (dir_static.d_name);
dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
dir_static.d_namlen - dir_static.d_namlen % 4;
return attrs;
}
+/* Ensure a network connection is authenticated. */
+static void
+logon_network_drive (const char *path)
+{
+ NETRESOURCE resource;
+ char share[MAX_PATH];
+ int i, n_slashes;
+ char drive[4];
+
+ sprintf (drive, "%c:\\", path[0]);
+
+ /* Only logon to networked drives. */
+ if ((!IS_DIRECTORY_SEP (path[0]) || !IS_DIRECTORY_SEP (path[1]))
+ && GetDriveType (drive) != DRIVE_REMOTE)
+ return;
+
+ n_slashes = 2;
+ strncpy (share, path, MAX_PATH);
+ /* Truncate to just server and share name. */
+ for (i = 2; i < MAX_PATH; i++)
+ {
+ if (IS_DIRECTORY_SEP (share[i]) && ++n_slashes > 3)
+ {
+ share[i] = '\0';
+ break;
+ }
+ }
+
+ resource.dwType = RESOURCETYPE_DISK;
+ resource.lpLocalName = NULL;
+ resource.lpRemoteName = share;
+ resource.lpProvider = NULL;
+
+ WNetAddConnection2 (&resource, NULL, NULL, CONNECT_INTERACTIVE);
+}
/* Shadow some MSVC runtime functions to map requests for long filenames
to reasonable short names if necessary. This was originally added to
int
sys_chown (const char *path, uid_t owner, gid_t group)
{
- if (sys_chmod (path, _S_IREAD) == -1) /* check if file exists */
+ if (sys_chmod (path, S_IREAD) == -1) /* check if file exists */
return -1;
return 0;
}
char *name, *r;
WIN32_FIND_DATA wfd;
HANDLE fh;
- DWORD fake_inode;
+ unsigned __int64 fake_inode;
int permission;
int len;
int rootdir = FALSE;
}
else
{
+ logon_network_drive (name);
+
fh = FindFirstFile (name, &wfd);
if (fh == INVALID_HANDLE_VALUE)
{
all the time (even then there are situations where it is
not unique). Reputedly, there are at most 48 bits of info
(on NTFS, presumably less on FAT). */
- fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
+ fake_inode = info.nFileIndexHigh;
+ fake_inode <<= 32;
+ fake_inode += info.nFileIndexLow;
}
else
{
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
- buf->st_mode = _S_IFDIR;
+ buf->st_mode = S_IFDIR;
}
else
{
switch (GetFileType (fh))
{
case FILE_TYPE_DISK:
- buf->st_mode = _S_IFREG;
+ buf->st_mode = S_IFREG;
break;
case FILE_TYPE_PIPE:
- buf->st_mode = _S_IFIFO;
+ buf->st_mode = S_IFIFO;
break;
case FILE_TYPE_CHAR:
case FILE_TYPE_UNKNOWN:
default:
- buf->st_mode = _S_IFCHR;
+ buf->st_mode = S_IFCHR;
}
}
CloseHandle (fh);
{
/* Don't bother to make this information more accurate. */
buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
- _S_IFDIR : _S_IFREG;
+ S_IFDIR : S_IFREG;
buf->st_nlink = 1;
fake_inode = 0;
}
/* determine rwx permissions */
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
- permission = _S_IREAD;
+ permission = S_IREAD;
else
- permission = _S_IREAD | _S_IWRITE;
+ permission = S_IREAD | S_IWRITE;
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- permission |= _S_IEXEC;
+ permission |= S_IEXEC;
else if (is_exec (name))
- permission |= _S_IEXEC;
+ permission |= S_IEXEC;
buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
{
HANDLE fh = (HANDLE) _get_osfhandle (desc);
BY_HANDLE_FILE_INFORMATION info;
- DWORD fake_inode;
+ unsigned __int64 fake_inode;
int permission;
switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
{
case FILE_TYPE_DISK:
- buf->st_mode = _S_IFREG;
+ buf->st_mode = S_IFREG;
if (!GetFileInformationByHandle (fh, &info))
{
errno = EACCES;
}
break;
case FILE_TYPE_PIPE:
- buf->st_mode = _S_IFIFO;
+ buf->st_mode = S_IFIFO;
goto non_disk;
case FILE_TYPE_CHAR:
case FILE_TYPE_UNKNOWN:
default:
- buf->st_mode = _S_IFCHR;
+ buf->st_mode = S_IFCHR;
non_disk:
memset (&info, 0, sizeof (info));
info.dwFileAttributes = 0;
}
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- buf->st_mode = _S_IFDIR;
+ buf->st_mode = S_IFDIR;
buf->st_nlink = info.nNumberOfLinks;
/* Might as well use file index to fake inode values, but this
all the time (even then there are situations where it is
not unique). Reputedly, there are at most 48 bits of info
(on NTFS, presumably less on FAT). */
- fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
+ fake_inode = info.nFileIndexHigh;
+ fake_inode <<= 32;
+ fake_inode += info.nFileIndexLow;
/* MSVC defines _ino_t to be short; other libc's might not. */
if (sizeof (buf->st_ino) == 2)
buf->st_ino = fake_inode;
/* consider files to belong to current user */
- buf->st_uid = 0;
- buf->st_gid = 0;
+ buf->st_uid = the_passwd.pw_uid;
+ buf->st_gid = the_passwd.pw_gid;
buf->st_dev = info.dwVolumeSerialNumber;
buf->st_rdev = info.dwVolumeSerialNumber;
/* determine rwx permissions */
if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
- permission = _S_IREAD;
+ permission = S_IREAD;
else
- permission = _S_IREAD | _S_IWRITE;
+ permission = S_IREAD | S_IWRITE;
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- permission |= _S_IEXEC;
+ permission |= S_IEXEC;
else
{
#if 0 /* no way of knowing the filename */
stricmp (p, ".com") == 0 ||
stricmp (p, ".bat") == 0 ||
stricmp (p, ".cmd") == 0))
- permission |= _S_IEXEC;
+ permission |= S_IEXEC;
#endif
}
void
globals_of_w32 ()
{
+ HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
+
+ get_process_times_fn = (GetProcessTimes_Proc)
+ GetProcAddress (kernel32, "GetProcessTimes");
+
g_b_init_is_windows_9x = 0;
g_b_init_open_process_token = 0;
g_b_init_get_token_information = 0;
g_b_init_lookup_account_sid = 0;
g_b_init_get_sid_identifier_authority = 0;
+ g_b_init_get_sid_sub_authority = 0;
+ g_b_init_get_sid_sub_authority_count = 0;
/* The following sets a handler for shutdown notifications for
console apps. This actually applies to Emacs in both console and
GUI modes, since we had to fool windows into thinking emacs is a