Mercurial > emacs
changeset 97491:bb6b5c0fc1ba
(CopySid_Proc, EqualSid_Proc, GetLengthSid_Proc): New typedefs.
(equal_sid, get_length_sid, copy_sid): New wrapper functions.
(w32_cached_id, w32_add_to_cache): New functions.
(get_name_and_id): Look account names in the cache before calling
lookup_account_sid.
(g_b_init_get_length_sid, g_b_init_equal_sid, g_b_init_copy_sid): New
initialization flags.
(globals_of_w32): Initialize them to zero.
(w32_system_process_attributes): Use w32_cached_id and w32_add_to_cache.
author | Eli Zaretskii <eliz@gnu.org> |
---|---|
date | Fri, 15 Aug 2008 15:59:48 +0000 |
parents | f8337cc2c494 |
children | c3951839aa67 |
files | src/w32.c |
diffstat | 1 files changed, 179 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/src/w32.c Fri Aug 15 13:54:14 2008 +0000 +++ b/src/w32.c Fri Aug 15 15:59:48 2008 +0000 @@ -188,6 +188,9 @@ static BOOL g_b_init_get_process_working_set_size; static BOOL g_b_init_global_memory_status; static BOOL g_b_init_global_memory_status_ex; +static BOOL g_b_init_get_length_sid; +static BOOL g_b_init_equal_sid; +static BOOL g_b_init_copy_sid; /* BEGIN: Wrapper functions around OpenProcessToken @@ -281,6 +284,17 @@ LPMEMORYSTATUS lpBuffer); typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) ( LPMEMORY_STATUS_EX lpBuffer); +typedef BOOL (WINAPI * CopySid_Proc) ( + DWORD nDestinationSidLength, + PSID pDestinationSid, + PSID pSourceSid); +typedef BOOL (WINAPI * EqualSid_Proc) ( + PSID pSid1, + PSID pSid2); +typedef DWORD (WINAPI * GetLengthSid_Proc) ( + PSID pSid); + + /* ** A utility function ** */ static BOOL @@ -628,6 +642,81 @@ return (s_pfn_Is_Valid_Sid (sid)); } +BOOL WINAPI equal_sid ( + PSID sid1, + PSID sid2) +{ + static EqualSid_Proc s_pfn_Equal_Sid = NULL; + HMODULE hm_advapi32 = NULL; + if (is_windows_9x () == TRUE) + { + return FALSE; + } + if (g_b_init_equal_sid == 0) + { + g_b_init_equal_sid = 1; + hm_advapi32 = LoadLibrary ("Advapi32.dll"); + s_pfn_Equal_Sid = + (EqualSid_Proc) GetProcAddress ( + hm_advapi32, "EqualSid"); + } + if (s_pfn_Equal_Sid == NULL) + { + return FALSE; + } + return (s_pfn_Equal_Sid (sid1, sid2)); +} + +DWORD WINAPI get_length_sid ( + PSID sid) +{ + static GetLengthSid_Proc s_pfn_Get_Length_Sid = NULL; + HMODULE hm_advapi32 = NULL; + if (is_windows_9x () == TRUE) + { + return 0; + } + if (g_b_init_get_length_sid == 0) + { + g_b_init_get_length_sid = 1; + hm_advapi32 = LoadLibrary ("Advapi32.dll"); + s_pfn_Get_Length_Sid = + (GetLengthSid_Proc) GetProcAddress ( + hm_advapi32, "GetLengthSid"); + } + if (s_pfn_Get_Length_Sid == NULL) + { + return 0; + } + return (s_pfn_Get_Length_Sid (sid)); +} + +BOOL WINAPI copy_sid ( + DWORD destlen, + PSID dest, + PSID src) +{ + static CopySid_Proc s_pfn_Copy_Sid = NULL; + HMODULE hm_advapi32 = NULL; + if (is_windows_9x () == TRUE) + { + return FALSE; + } + if (g_b_init_copy_sid == 0) + { + g_b_init_copy_sid = 1; + hm_advapi32 = LoadLibrary ("Advapi32.dll"); + s_pfn_Copy_Sid = + (CopySid_Proc) GetProcAddress ( + hm_advapi32, "CopySid"); + } + if (s_pfn_Copy_Sid == NULL) + { + return FALSE; + } + return (s_pfn_Copy_Sid (destlen, dest, src)); +} + /* END: Wrapper functions around OpenProcessToken and other functions in advapi32.dll that are only @@ -2780,6 +2869,69 @@ return *get_sid_sub_authority (sid, n_subauthorities - 1); } +/* Caching SID and account values for faster lokup. */ + +#ifdef __GNUC__ +# define FLEXIBLE_ARRAY_MEMBER +#else +# define FLEXIBLE_ARRAY_MEMBER 1 +#endif + +struct w32_id { + int rid; + struct w32_id *next; + char name[GNLEN+1]; + unsigned char sid[FLEXIBLE_ARRAY_MEMBER]; +}; + +static struct w32_id *w32_idlist; + +static int +w32_cached_id (PSID sid, int *id, char *name) +{ + struct w32_id *tail, *found; + + for (found = NULL, tail = w32_idlist; tail; tail = tail->next) + { + if (equal_sid ((PSID)tail->sid, sid)) + { + found = tail; + break; + } + } + if (found) + { + *id = found->rid; + strcpy (name, found->name); + return 1; + } + else + return 0; +} + +static void +w32_add_to_cache (PSID sid, int id, char *name) +{ + DWORD sid_len; + struct w32_id *new_entry; + + /* We don't want to leave behind stale cache from when Emacs was + dumped. */ + if (initialized) + { + sid_len = get_length_sid (sid); + new_entry = xmalloc (offsetof (struct w32_id, sid) + sid_len); + if (new_entry) + { + new_entry->rid = id; + strcpy (new_entry->name, name); + copy_sid (sid_len, (PSID)new_entry->sid, sid); + new_entry->next = w32_idlist; + w32_idlist = new_entry; + } + } +} + #define UID 1 #define GID 2 @@ -2808,7 +2960,7 @@ if (!result || !is_valid_sid (sid)) use_dflt = 1; - else + else if (!w32_cached_id (sid, id, nm)) { /* If FNAME is a UNC, we need to lookup account on the specified machine. */ @@ -2833,6 +2985,7 @@ { *id = get_rid (sid); strcpy (nm, name); + w32_add_to_cache (sid, *id, name); } } return use_dflt; @@ -3748,11 +3901,18 @@ if (h_proc && open_process_token (h_proc, TOKEN_QUERY, &token) && get_token_information (token, TokenUser, - (PVOID)buf, sizeof (buf), &trash) - && (memcpy (&user_token, buf, sizeof (user_token)), + (PVOID)buf, sizeof (buf), &trash)) + { + memcpy (&user_token, buf, sizeof (user_token)); + if (w32_cached_id (user_token.User.Sid, &euid, uname)) + ulength = strlen (uname); + else + { lookup_account_sid (NULL, user_token.User.Sid, uname, &ulength, - domain, &dlength, &user_type))) - { + domain, &dlength, &user_type); + euid = get_rid (user_token.User.Sid); + w32_add_to_cache (user_token.User.Sid, euid, uname); + } /* Determine a reasonable euid and gid values. */ if (xstrcasecmp ("administrator", uname) == 0) { @@ -3761,20 +3921,22 @@ } else { - /* Use the last sub-authority value of the RID, the relative - portion of the SID, as user/group ID. */ - euid = get_rid (user_token.User.Sid); - /* Get group id and name. */ if (get_token_information (token, TokenPrimaryGroup, (PVOID)buf, sizeof (buf), &trash)) { memcpy (&group_token, buf, sizeof (group_token)); - egid = get_rid (group_token.PrimaryGroup); - dlength = sizeof (domain); - lookup_account_sid (NULL, group_token.PrimaryGroup, - gname, &glength, NULL, &dlength, - &user_type); + if (w32_cached_id (group_token.PrimaryGroup, &egid, gname)) + glength = strlen (gname); + else + { + dlength = sizeof (domain); + lookup_account_sid (NULL, group_token.PrimaryGroup, + gname, &glength, NULL, &dlength, + &user_type); + egid = get_rid (group_token.PrimaryGroup); + w32_add_to_cache (group_token.PrimaryGroup, egid, gname); + } } else egid = euid; @@ -5457,6 +5619,9 @@ g_b_init_get_process_working_set_size = 0; g_b_init_global_memory_status = 0; g_b_init_global_memory_status_ex = 0; + g_b_init_equal_sid = 0; + g_b_init_copy_sid = 0; + g_b_init_get_length_sid = 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