728 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			728 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
/* cygheap.h: Cygwin heap manager.
 | 
						|
 | 
						|
This file is part of Cygwin.
 | 
						|
 | 
						|
This software is a copyrighted work licensed under the terms of the
 | 
						|
Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
 | 
						|
details. */
 | 
						|
 | 
						|
#include "hires.h"
 | 
						|
#include "cygheap_malloc.h"
 | 
						|
#include "pwdgrp.h"
 | 
						|
 | 
						|
#define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap_max)))
 | 
						|
 | 
						|
struct _cmalloc_entry
 | 
						|
{
 | 
						|
  union
 | 
						|
  {
 | 
						|
    unsigned b;
 | 
						|
    char *ptr;
 | 
						|
  };
 | 
						|
  struct _cmalloc_entry *prev;
 | 
						|
  char data[0];
 | 
						|
};
 | 
						|
 | 
						|
struct cygheap_root_mount_info
 | 
						|
{
 | 
						|
  char posix_path[CYG_MAX_PATH];
 | 
						|
  unsigned posix_pathlen;
 | 
						|
  char native_path[CYG_MAX_PATH];
 | 
						|
  unsigned native_pathlen;
 | 
						|
  bool caseinsensitive;
 | 
						|
};
 | 
						|
 | 
						|
/* CGF: FIXME This doesn't belong here */
 | 
						|
 | 
						|
class cygheap_root
 | 
						|
{
 | 
						|
  /* Root directory information.
 | 
						|
     This is used after a chroot is called. */
 | 
						|
  struct cygheap_root_mount_info *m;
 | 
						|
 | 
						|
public:
 | 
						|
  bool posix_ok (const char *path)
 | 
						|
  {
 | 
						|
    if (!m)
 | 
						|
      return 1;
 | 
						|
    return path_prefix_p (m->posix_path, path, m->posix_pathlen,
 | 
						|
			  m->caseinsensitive);
 | 
						|
  }
 | 
						|
  bool ischroot_native (const char *path)
 | 
						|
  {
 | 
						|
    if (!m)
 | 
						|
      return 1;
 | 
						|
    return strncasematch (m->native_path, path, m->native_pathlen)
 | 
						|
	    && (path[m->native_pathlen] == '\\' || !path[m->native_pathlen]);
 | 
						|
  }
 | 
						|
  const char *unchroot (const char *path)
 | 
						|
  {
 | 
						|
    if (!m)
 | 
						|
      return path;
 | 
						|
    const char *p = path + m->posix_pathlen;
 | 
						|
    if (!*p)
 | 
						|
      p = "/";
 | 
						|
    return p;
 | 
						|
  }
 | 
						|
  bool exists () {return !!m;}
 | 
						|
  void set (const char *, const char *, bool);
 | 
						|
  size_t posix_length () const { return m->posix_pathlen; }
 | 
						|
  const char *posix_path () const { return m->posix_path; }
 | 
						|
  size_t native_length () const { return m->native_pathlen; }
 | 
						|
  const char *native_path () const { return m->native_path; }
 | 
						|
};
 | 
						|
 | 
						|
enum homebodies
 | 
						|
{
 | 
						|
  CH_HOMEDRIVE,
 | 
						|
  CH_HOMEPATH,
 | 
						|
  CH_HOME
 | 
						|
};
 | 
						|
 | 
						|
class cygheap_user
 | 
						|
{
 | 
						|
  /* Extendend user information.
 | 
						|
     The information is derived from the internal_getlogin call
 | 
						|
     when on a NT system. */
 | 
						|
  char  *pname;		/* user's name */
 | 
						|
  char  *plogsrv;       /* Logon server, may be FQDN */
 | 
						|
  char  *pdomain;       /* Logon domain of the user */
 | 
						|
  char  *homedrive;	/* User's home drive */
 | 
						|
  char  *homepath;	/* User's home path */
 | 
						|
  char  *psystemroot;	/* Value of SYSTEMROOT */
 | 
						|
  char  *pwinname;	/* User's name as far as Windows knows it */
 | 
						|
  char  *puserprof;	/* User profile */
 | 
						|
  cygsid effec_cygsid;  /* buffer for user's SID */
 | 
						|
  cygsid saved_cygsid;  /* Remains intact even after impersonation */
 | 
						|
public:
 | 
						|
  uid_t saved_uid;      /* Remains intact even after impersonation */
 | 
						|
  gid_t saved_gid;      /* Ditto */
 | 
						|
  uid_t real_uid;       /* Remains intact on seteuid, replaced by setuid */
 | 
						|
  gid_t real_gid;       /* Ditto */
 | 
						|
  user_groups groups;   /* Primary and supp SIDs */
 | 
						|
 | 
						|
  /* token is needed if set(e)uid should be called. It can be set by a call
 | 
						|
     to `set_impersonation_token()'. */
 | 
						|
  HANDLE external_token;
 | 
						|
  HANDLE internal_token;
 | 
						|
  HANDLE curr_primary_token;
 | 
						|
  HANDLE curr_imp_token;
 | 
						|
  bool ext_token_is_restricted;  /* external_token is restricted token */
 | 
						|
  bool curr_token_is_restricted; /* curr_primary_token is restricted token */
 | 
						|
  bool setuid_to_restricted;     /* switch to restricted token by setuid () */
 | 
						|
 | 
						|
  /* CGF 2002-06-27.  I removed the initializaton from this constructor
 | 
						|
     since this class is always allocated statically.  That means that everything
 | 
						|
     is zero anyway so there is no need to initialize it to zero.  Since the
 | 
						|
     token initialization is always handled during process startup as well,
 | 
						|
     I've removed the constructor entirely.  Please reinstate this if this
 | 
						|
     situation ever changes.
 | 
						|
  cygheap_user () : pname (NULL), plogsrv (NULL), pdomain (NULL),
 | 
						|
		    homedrive (NULL), homepath (NULL),
 | 
						|
		    token (INVALID_HANDLE_VALUE) {}
 | 
						|
  */
 | 
						|
 | 
						|
  ~cygheap_user ();
 | 
						|
 | 
						|
  void init ();
 | 
						|
  void set_name (const char *new_name);
 | 
						|
  const char *name () const { return pname; }
 | 
						|
 | 
						|
  const char *env_logsrv (const char *, size_t);
 | 
						|
  const char *env_homepath (const char *, size_t);
 | 
						|
  const char *env_homedrive (const char *, size_t);
 | 
						|
  const char *env_userprofile (const char *, size_t);
 | 
						|
  const char *env_domain (const char *, size_t);
 | 
						|
  const char *env_name (const char *, size_t);
 | 
						|
  const char *env_systemroot (const char *, size_t);
 | 
						|
 | 
						|
  const char *logsrv ()
 | 
						|
  {
 | 
						|
    const char *p = env_logsrv ("LOGONSERVER=", sizeof ("LOGONSERVER=") - 1);
 | 
						|
    return (p == almost_null) ? NULL : p;
 | 
						|
  }
 | 
						|
  const char *winname ()
 | 
						|
  {
 | 
						|
    const char *p = env_name ("USERNAME=", sizeof ("USERNAME=") - 1);
 | 
						|
    return (p == almost_null) ? NULL : p;
 | 
						|
  }
 | 
						|
  const char *domain ()
 | 
						|
  {
 | 
						|
    const char *p = env_domain ("USERDOMAIN=", sizeof ("USERDOMAIN=") - 1);
 | 
						|
    return (p == almost_null) ? NULL : p;
 | 
						|
  }
 | 
						|
  void set_sid (PSID new_sid) { effec_cygsid = new_sid;}
 | 
						|
  void set_saved_sid () { saved_cygsid = effec_cygsid; }
 | 
						|
  cygpsid &sid () { return effec_cygsid; }
 | 
						|
  cygpsid &saved_sid () { return saved_cygsid; }
 | 
						|
  const char *ontherange (homebodies what, struct passwd * = NULL);
 | 
						|
#define NO_IMPERSONATION NULL
 | 
						|
  bool issetuid () const { return curr_imp_token != NO_IMPERSONATION; }
 | 
						|
  HANDLE primary_token () { return curr_primary_token; }
 | 
						|
  HANDLE imp_token () { return curr_imp_token; }
 | 
						|
  void deimpersonate ()
 | 
						|
  {
 | 
						|
    RevertToSelf ();
 | 
						|
  }
 | 
						|
  bool reimpersonate ()
 | 
						|
  {
 | 
						|
    if (issetuid ())
 | 
						|
      return ImpersonateLoggedOnUser (primary_token ());
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  bool has_impersonation_tokens ()
 | 
						|
    { return external_token != NO_IMPERSONATION
 | 
						|
	     || internal_token != NO_IMPERSONATION
 | 
						|
	     || curr_primary_token != NO_IMPERSONATION; }
 | 
						|
  void close_impersonation_tokens ()
 | 
						|
  {
 | 
						|
    if (curr_imp_token != NO_IMPERSONATION)
 | 
						|
      CloseHandle (curr_imp_token);
 | 
						|
    if (curr_primary_token != NO_IMPERSONATION
 | 
						|
	&& curr_primary_token != external_token
 | 
						|
	&& curr_primary_token != internal_token)
 | 
						|
      CloseHandle (curr_primary_token);
 | 
						|
    if (external_token != NO_IMPERSONATION)
 | 
						|
      CloseHandle (external_token);
 | 
						|
    if (internal_token != NO_IMPERSONATION)
 | 
						|
      CloseHandle (internal_token);
 | 
						|
  }
 | 
						|
  PWCHAR get_windows_id (PWCHAR buf)
 | 
						|
  {
 | 
						|
    return effec_cygsid.string (buf);
 | 
						|
  }
 | 
						|
  char *get_windows_id (char *buf)
 | 
						|
  {
 | 
						|
    return effec_cygsid.string (buf);
 | 
						|
  }
 | 
						|
 | 
						|
  const char __reg3 *test_uid (char *&, const char *, size_t);
 | 
						|
};
 | 
						|
 | 
						|
/* cwd cache stuff.  */
 | 
						|
 | 
						|
enum fcwd_version_t {
 | 
						|
  FCWD_OLD,
 | 
						|
  FCWD_W7,
 | 
						|
  FCWD_W8
 | 
						|
};
 | 
						|
 | 
						|
/* This class is used to store the CWD.  The CWD storage in the
 | 
						|
   RTL_USER_PROCESS_PARAMETERS block is only an afterthought now.  The actual
 | 
						|
   CWD storage is a FAST_CWD structure which is allocated on the process heap.
 | 
						|
   The new method only requires minimal locking and it's much more multi-thread
 | 
						|
   friendly.  Presumably it minimizes contention when accessing the CWD.
 | 
						|
   The class fcwd_access_t is supposed to encapsulate the gory implementation
 | 
						|
   details depending on OS version from the calling functions.
 | 
						|
   The layout of all structures has been tested on 32 and 64 bit. */
 | 
						|
class fcwd_access_t {
 | 
						|
  /* This is the layout used in Windows 8 and later. */
 | 
						|
  struct FAST_CWD_8 {
 | 
						|
    LONG           ReferenceCount;	/* Only release when this is 0. */
 | 
						|
    HANDLE         DirectoryHandle;
 | 
						|
    ULONG          OldDismountCount;	/* Reflects the system DismountCount
 | 
						|
					   at the time the CWD has been set. */
 | 
						|
    UNICODE_STRING Path;		/* Path's Buffer member always refers
 | 
						|
					   to the following Buffer array. */
 | 
						|
    LONG           FSCharacteristics;	/* Taken from FileFsDeviceInformation */
 | 
						|
    WCHAR          Buffer[MAX_PATH] __attribute ((aligned (8)));
 | 
						|
  };
 | 
						|
  /* This is the layout used in Windows 7 and Vista. */
 | 
						|
  struct FAST_CWD_7 {
 | 
						|
    UNICODE_STRING Path;		/* Path's Buffer member always refers
 | 
						|
					   to the following Buffer array. */
 | 
						|
    HANDLE         DirectoryHandle;
 | 
						|
    LONG           FSCharacteristics;	/* Taken from FileFsDeviceInformation */
 | 
						|
    LONG           ReferenceCount;	/* Only release when this is 0. */
 | 
						|
    ULONG          OldDismountCount;	/* Reflects the system DismountCount
 | 
						|
					   at the time the CWD has been set. */
 | 
						|
    WCHAR          Buffer[MAX_PATH] __attribute ((aligned (8)));
 | 
						|
  };
 | 
						|
  /* This is the old FAST_CWD structure up to the patch from KB 2393802,
 | 
						|
     release in February 2011. */
 | 
						|
  struct FAST_CWD_OLD {
 | 
						|
    LONG           ReferenceCount;	/* Only release when this is 0. */
 | 
						|
    HANDLE         DirectoryHandle;
 | 
						|
    ULONG          OldDismountCount;	/* Reflects the system DismountCount
 | 
						|
					   at the time the CWD has been set. */
 | 
						|
    UNICODE_STRING Path;		/* Path's Buffer member always refers
 | 
						|
					   to the following Buffer array. */
 | 
						|
    WCHAR          Buffer[MAX_PATH];
 | 
						|
  };
 | 
						|
  union {
 | 
						|
    FAST_CWD_OLD fold;
 | 
						|
    FAST_CWD_7   f7;
 | 
						|
    FAST_CWD_8   f8;
 | 
						|
  };
 | 
						|
 | 
						|
#define IMPLEMENT(type, name) \
 | 
						|
  type name () { \
 | 
						|
    switch (fast_cwd_version ()) { \
 | 
						|
      case FCWD_OLD: \
 | 
						|
      default: \
 | 
						|
	return fold.name; \
 | 
						|
      case FCWD_W7: \
 | 
						|
	return f7.name; \
 | 
						|
      case FCWD_W8: \
 | 
						|
	return f8.name; \
 | 
						|
    } \
 | 
						|
  }
 | 
						|
  IMPLEMENT (LONG &, ReferenceCount)
 | 
						|
  IMPLEMENT (HANDLE &, DirectoryHandle)
 | 
						|
  IMPLEMENT (ULONG &, OldDismountCount)
 | 
						|
  IMPLEMENT (UNICODE_STRING &, Path)
 | 
						|
  IMPLEMENT (WCHAR *, Buffer)
 | 
						|
  void SetFSCharacteristics (LONG val);
 | 
						|
  static fcwd_version_t &fast_cwd_version (void);
 | 
						|
 | 
						|
public:
 | 
						|
  void CopyPath (UNICODE_STRING &target);
 | 
						|
  void Free (PVOID heap);
 | 
						|
  void FillIn (HANDLE dir, PUNICODE_STRING name, ULONG old_dismount_count);
 | 
						|
  static void SetDirHandleFromBufferPointer (PWCHAR buf_p, HANDLE dir);
 | 
						|
  static void SetVersionFromPointer (PBYTE buf_p, bool is_buffer);
 | 
						|
};
 | 
						|
 | 
						|
class cwdstuff
 | 
						|
{
 | 
						|
private:
 | 
						|
  char *posix;
 | 
						|
  HANDLE dir;
 | 
						|
  DWORD drive_length;
 | 
						|
  int error;		/* This contains an errno number which corresponds
 | 
						|
			   to the problem with this path when trying to start
 | 
						|
			   a native Win32 application.  See cwdstuff::set for
 | 
						|
			   how it gets set.  See child_info_spawn::worker for how
 | 
						|
			   it's evaluated. */
 | 
						|
 | 
						|
  friend class fcwd_access_t;
 | 
						|
  /* fast_cwd_ptr is a pointer to the global RtlpCurDirRef pointer in
 | 
						|
     ntdll.dll pointing to the FAST_CWD structure which constitutes the CWD.
 | 
						|
     Unfortunately RtlpCurDirRef is not exported from ntdll.dll. */
 | 
						|
  fcwd_access_t **fast_cwd_ptr;
 | 
						|
  /* Type of FAST_CWD used on this system.  Keeping this information
 | 
						|
     available in shared memory avoids to test for the version every time
 | 
						|
     around.  Default to new version. */
 | 
						|
  fcwd_version_t fast_cwd_version;
 | 
						|
  void override_win32_cwd (bool init, ULONG old_dismount_count);
 | 
						|
 | 
						|
public:
 | 
						|
  UNICODE_STRING win32;
 | 
						|
  static muto cwd_lock;
 | 
						|
  const char *get_posix () const { return posix; };
 | 
						|
  void reset_posix (wchar_t *w_cwd);
 | 
						|
  char *get (char *buf, int need_posix = 1, int with_chroot = 0,
 | 
						|
	     unsigned ulen = NT_MAX_PATH);
 | 
						|
  PWCHAR get (PWCHAR buf, unsigned buflen = NT_MAX_PATH)
 | 
						|
  {
 | 
						|
    cwd_lock.acquire ();
 | 
						|
    buf[0] = L'\0';
 | 
						|
    wcsncat (buf, win32.Buffer, buflen - 1);
 | 
						|
    cwd_lock.release ();
 | 
						|
    return buf;
 | 
						|
  }
 | 
						|
  HANDLE get_handle () { return dir; }
 | 
						|
  DWORD get_drive (char * dst)
 | 
						|
  {
 | 
						|
    cwd_lock.acquire ();
 | 
						|
    DWORD ret = sys_wcstombs (dst, NT_MAX_PATH, win32.Buffer, drive_length);
 | 
						|
    cwd_lock.release ();
 | 
						|
    return ret;
 | 
						|
  }
 | 
						|
  int get_error () const { return error; }
 | 
						|
  const char *get_error_desc () const;
 | 
						|
  void init ();
 | 
						|
  int set (path_conv *, const char *);
 | 
						|
};
 | 
						|
 | 
						|
#ifdef DEBUGGING
 | 
						|
struct cygheap_debug
 | 
						|
{
 | 
						|
  handle_list starth;
 | 
						|
  handle_list freeh[500];
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
struct cygheap_locale
 | 
						|
{
 | 
						|
  mbtowc_p mbtowc;
 | 
						|
};
 | 
						|
 | 
						|
struct user_heap_info
 | 
						|
{
 | 
						|
  void *base;
 | 
						|
  void *ptr;
 | 
						|
  void *top;
 | 
						|
  void *max;
 | 
						|
  SIZE_T chunk;
 | 
						|
  void __reg2 *sbrk (ptrdiff_t);
 | 
						|
  void __reg1 init ();
 | 
						|
};
 | 
						|
 | 
						|
class cygheap_domain_info
 | 
						|
{
 | 
						|
  PWCHAR pdom_name;
 | 
						|
  PWCHAR pdom_dns_name;
 | 
						|
  cygsid pdom_sid;
 | 
						|
 | 
						|
  PWCHAR adom_name;
 | 
						|
  cygsid adom_sid;
 | 
						|
 | 
						|
  PDS_DOMAIN_TRUSTSW tdom;
 | 
						|
  ULONG tdom_count;
 | 
						|
 | 
						|
  PWCHAR rfc2307_domain_buf;
 | 
						|
 | 
						|
public:
 | 
						|
  bool init ();
 | 
						|
 | 
						|
  inline PCWSTR primary_flat_name () const { return pdom_name; }
 | 
						|
  inline PCWSTR primary_dns_name () const { return pdom_dns_name; }
 | 
						|
  inline cygsid &primary_sid () { return pdom_sid; }
 | 
						|
 | 
						|
  inline bool member_machine () const { return pdom_sid != NO_SID; }
 | 
						|
 | 
						|
  inline PCWSTR account_flat_name () const { return adom_name; }
 | 
						|
  inline cygsid &account_sid () { return adom_sid; }
 | 
						|
 | 
						|
  inline PDS_DOMAIN_TRUSTSW trusted_domain (ULONG idx) const
 | 
						|
    { return (idx < tdom_count) ? tdom + idx : NULL; }
 | 
						|
  PDS_DOMAIN_TRUSTSW add_domain (PCWSTR, PSID);
 | 
						|
 | 
						|
  inline PWCHAR get_rfc2307_domain () const
 | 
						|
    { return rfc2307_domain_buf ?: NULL; }
 | 
						|
};
 | 
						|
 | 
						|
class cygheap_pwdgrp
 | 
						|
{
 | 
						|
  enum nss_pfx_t {
 | 
						|
    NSS_PFX_AUTO = 0,
 | 
						|
    NSS_PFX_PRIMARY,
 | 
						|
    NSS_PFX_ALWAYS
 | 
						|
  };
 | 
						|
public:
 | 
						|
  enum nss_scheme_method {
 | 
						|
    NSS_SCHEME_FALLBACK = 0,
 | 
						|
    NSS_SCHEME_WINDOWS,
 | 
						|
    NSS_SCHEME_CYGWIN,
 | 
						|
    NSS_SCHEME_UNIX,
 | 
						|
    NSS_SCHEME_DESC,
 | 
						|
    NSS_SCHEME_PATH,
 | 
						|
    NSS_SCHEME_FREEATTR
 | 
						|
  };
 | 
						|
  struct nss_scheme_t {
 | 
						|
    nss_scheme_method	method;
 | 
						|
    PWCHAR		attrib;
 | 
						|
  };
 | 
						|
private:
 | 
						|
  bool		nss_inited;
 | 
						|
  uint32_t	pwd_src;
 | 
						|
  uint32_t	grp_src;
 | 
						|
  nss_pfx_t	prefix;
 | 
						|
  WCHAR		separator[2];
 | 
						|
  bool		caching;
 | 
						|
 | 
						|
#define NSS_SCHEME_MAX	4
 | 
						|
  nss_scheme_t	home_scheme[NSS_SCHEME_MAX];
 | 
						|
  nss_scheme_t	shell_scheme[NSS_SCHEME_MAX];
 | 
						|
  nss_scheme_t	gecos_scheme[NSS_SCHEME_MAX];
 | 
						|
 | 
						|
  uint32_t	enums;
 | 
						|
  PWCHAR	enum_tdoms;
 | 
						|
 | 
						|
  void nss_init_line (const char *line);
 | 
						|
  void _nss_init ();
 | 
						|
 | 
						|
public:
 | 
						|
  struct {
 | 
						|
    pwdgrp cygserver;
 | 
						|
    pwdgrp file;
 | 
						|
    pwdgrp win;
 | 
						|
  } pwd_cache;
 | 
						|
  struct {
 | 
						|
    pwdgrp cygserver;
 | 
						|
    pwdgrp file;
 | 
						|
    pwdgrp win;
 | 
						|
  } grp_cache;
 | 
						|
 | 
						|
  void init ();
 | 
						|
 | 
						|
  /* Implemented in ldap.cc */
 | 
						|
  PWCHAR *ldap_user_attr;
 | 
						|
  void init_ldap_user_attr ();
 | 
						|
 | 
						|
  inline void nss_init () { if (!nss_inited) _nss_init (); }
 | 
						|
  inline bool nss_pwd_files () const { return !!(pwd_src & NSS_SRC_FILES); }
 | 
						|
  inline bool nss_pwd_db () const { return !!(pwd_src & NSS_SRC_DB); }
 | 
						|
  inline int  nss_pwd_src () const { return pwd_src; } /* CW_GETNSS_PWD_SRC */
 | 
						|
  inline bool nss_grp_files () const { return !!(grp_src & NSS_SRC_FILES); }
 | 
						|
  inline bool nss_grp_db () const { return !!(grp_src & NSS_SRC_DB); }
 | 
						|
  inline int  nss_grp_src () const { return grp_src; } /* CW_GETNSS_GRP_SRC */
 | 
						|
  inline bool nss_prefix_auto () const { return prefix == NSS_PFX_AUTO; }
 | 
						|
  inline bool nss_prefix_primary () const { return prefix == NSS_PFX_PRIMARY; }
 | 
						|
  inline bool nss_prefix_always () const { return prefix == NSS_PFX_ALWAYS; }
 | 
						|
  inline PCWSTR nss_separator () const { return separator; }
 | 
						|
  inline bool nss_cygserver_caching () const { return caching; }
 | 
						|
  inline void nss_disable_cygserver_caching () { caching = false; }
 | 
						|
 | 
						|
  char *get_home (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, PCWSTR dnsdomain,
 | 
						|
		  PCWSTR name, bool fq);
 | 
						|
  char *get_home (struct _USER_INFO_3 *ui, cygpsid &sid, PCWSTR dom,
 | 
						|
		  PCWSTR name, bool fq);
 | 
						|
 | 
						|
  char *get_shell (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, PCWSTR dnsdomain,
 | 
						|
		   PCWSTR name, bool fq);
 | 
						|
  char *get_shell (struct _USER_INFO_3 *ui, cygpsid &sid, PCWSTR dom,
 | 
						|
		   PCWSTR name, bool fq);
 | 
						|
 | 
						|
  char *get_gecos (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, PCWSTR dnsdomain,
 | 
						|
		   PCWSTR name, bool fq);
 | 
						|
  char *get_gecos (struct _USER_INFO_3 *ui, cygpsid &sid, PCWSTR dom,
 | 
						|
		   PCWSTR name, bool fq);
 | 
						|
 | 
						|
  inline int nss_db_enums () const { return enums; }
 | 
						|
  inline PCWSTR nss_db_enum_tdoms () const { return enum_tdoms; }
 | 
						|
};
 | 
						|
 | 
						|
class cygheap_ugid_cache
 | 
						|
{
 | 
						|
  struct idmap {
 | 
						|
    uint32_t nfs_id;
 | 
						|
    uint32_t cyg_id;
 | 
						|
  };
 | 
						|
  class idmaps {
 | 
						|
    uint32_t _cnt;
 | 
						|
    uint32_t _max;
 | 
						|
    idmap *_map;
 | 
						|
  public:
 | 
						|
    uint32_t get (uint32_t id) const
 | 
						|
    {
 | 
						|
      for (uint32_t i = 0; i < _cnt; ++i)
 | 
						|
	if (_map[i].nfs_id == id)
 | 
						|
	  return _map[i].cyg_id;
 | 
						|
      return (uint32_t) -1;
 | 
						|
    }
 | 
						|
    uint32_t reverse_get (uint32_t id) const
 | 
						|
    {
 | 
						|
      for (uint32_t i = 0; i < _cnt; ++i)
 | 
						|
	if (_map[i].cyg_id == id)
 | 
						|
	  return _map[i].nfs_id;
 | 
						|
      return (uint32_t) -1;
 | 
						|
    }
 | 
						|
    void add (uint32_t nfs_id, uint32_t cyg_id)
 | 
						|
    {
 | 
						|
      if (_cnt >= _max)
 | 
						|
	_map = (idmap *) crealloc (_map, (_max += 10) * sizeof (*_map));
 | 
						|
      _map[_cnt].nfs_id = nfs_id;
 | 
						|
      _map[_cnt].cyg_id = cyg_id;
 | 
						|
      ++_cnt;
 | 
						|
    }
 | 
						|
  };
 | 
						|
  idmaps uids;
 | 
						|
  idmaps gids;
 | 
						|
 | 
						|
public:
 | 
						|
  uid_t get_uid (uid_t uid) const { return uids.get (uid); }
 | 
						|
  gid_t get_gid (gid_t gid) const { return gids.get (gid); }
 | 
						|
  uid_t reverse_get_uid (uid_t uid) const { return uids.reverse_get (uid); }
 | 
						|
  gid_t reverse_get_gid (gid_t gid) const { return gids.reverse_get (gid); }
 | 
						|
  void add_uid (uid_t nfs_uid, uid_t cyg_uid) { uids.add (nfs_uid, cyg_uid); }
 | 
						|
  void add_gid (gid_t nfs_gid, gid_t cyg_gid) { gids.add (nfs_gid, cyg_gid); }
 | 
						|
};
 | 
						|
 | 
						|
struct hook_chain
 | 
						|
{
 | 
						|
  void **loc;
 | 
						|
  const void *func;
 | 
						|
  struct hook_chain *next;
 | 
						|
};
 | 
						|
 | 
						|
struct mini_cygheap
 | 
						|
{
 | 
						|
  cygheap_locale locale;
 | 
						|
};
 | 
						|
 | 
						|
#define NBUCKETS 40
 | 
						|
 | 
						|
struct threadlist_t
 | 
						|
{
 | 
						|
  struct _cygtls *thread;
 | 
						|
  HANDLE mutex;			/* Used to avoid accessing tls area of
 | 
						|
				   deleted thread.  See comment in
 | 
						|
				   cygheap::remove_tls for a description. */
 | 
						|
};
 | 
						|
 | 
						|
struct init_cygheap: public mini_cygheap
 | 
						|
{
 | 
						|
  _cmalloc_entry *chain;
 | 
						|
  unsigned bucket_val[NBUCKETS];
 | 
						|
  char *buckets[NBUCKETS];
 | 
						|
  WCHAR installation_root[PATH_MAX];
 | 
						|
  WCHAR installation_dir[PATH_MAX];
 | 
						|
  size_t installation_dir_len;
 | 
						|
  UNICODE_STRING installation_key;
 | 
						|
  WCHAR installation_key_buf[18];
 | 
						|
  cygheap_root root;
 | 
						|
  cygheap_domain_info dom;
 | 
						|
  cygheap_pwdgrp pg;
 | 
						|
  cygheap_ugid_cache ugid_cache;
 | 
						|
  cygheap_user user;
 | 
						|
  user_heap_info user_heap;
 | 
						|
  mode_t umask;
 | 
						|
  unsigned long rlim_core;
 | 
						|
  HANDLE console_h;
 | 
						|
  cwdstuff cwd;
 | 
						|
  dtable fdtab;
 | 
						|
#ifdef DEBUGGING
 | 
						|
  cygheap_debug debug;
 | 
						|
#endif
 | 
						|
  struct sigaction *sigs;
 | 
						|
 | 
						|
  fhandler_termios *ctty;	/* Current tty */
 | 
						|
  threadlist_t *threadlist;
 | 
						|
  uint32_t sthreads;
 | 
						|
  pid_t pid;			/* my pid */
 | 
						|
  struct {			/* Equivalent to using LIST_HEAD. */
 | 
						|
    struct inode_t *lh_first;
 | 
						|
  } inode_list;			/* Global inode pointer for adv. locking. */
 | 
						|
  hook_chain hooks;
 | 
						|
  void close_ctty ();
 | 
						|
  void init_installation_root ();
 | 
						|
  void __reg1 init_tls_list ();;
 | 
						|
  void __reg2 add_tls (_cygtls *);
 | 
						|
  HANDLE __reg3 remove_tls (_cygtls *);
 | 
						|
  threadlist_t __reg2 *find_tls (_cygtls *);
 | 
						|
  threadlist_t __reg3 *find_tls (int, bool&);
 | 
						|
  void unlock_tls (threadlist_t *t) { if (t) ReleaseMutex (t->mutex); }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
#define _CYGHEAPSIZE_SLOP (128 * 1024)
 | 
						|
#define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + _CYGHEAPSIZE_SLOP)
 | 
						|
#define CYGHEAPSIZE_MIN (sizeof (init_cygheap) + (10000 * sizeof (fhandler_union)))
 | 
						|
 | 
						|
extern init_cygheap *cygheap;
 | 
						|
extern void *cygheap_max;
 | 
						|
 | 
						|
class cygheap_fdmanip
 | 
						|
{
 | 
						|
 protected:
 | 
						|
  int fd;
 | 
						|
  bool locked;
 | 
						|
 public:
 | 
						|
  cygheap_fdmanip (): fd (-1), locked (false) {}
 | 
						|
  virtual ~cygheap_fdmanip ()
 | 
						|
  {
 | 
						|
    if (locked)
 | 
						|
      cygheap->fdtab.unlock ();
 | 
						|
  }
 | 
						|
  virtual void release () { cygheap->fdtab.release (fd); }
 | 
						|
  operator int &() {return fd;}
 | 
						|
  operator fhandler_base* &() {return cygheap->fdtab[fd];}
 | 
						|
  operator fhandler_socket* () const {return reinterpret_cast<fhandler_socket *> (cygheap->fdtab[fd]);}
 | 
						|
  operator fhandler_pipe* () const {return reinterpret_cast<fhandler_pipe *> (cygheap->fdtab[fd]);}
 | 
						|
  void operator = (fhandler_base *fh) {cygheap->fdtab[fd] = fh;}
 | 
						|
  fhandler_base *operator -> () const {return cygheap->fdtab[fd];}
 | 
						|
  bool isopen () const
 | 
						|
  {
 | 
						|
    if (cygheap->fdtab[fd])
 | 
						|
      return true;
 | 
						|
    set_errno (EBADF);
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class cygheap_fdnew : public cygheap_fdmanip
 | 
						|
{
 | 
						|
 public:
 | 
						|
  cygheap_fdnew (int seed_fd = -1, bool lockit = true)
 | 
						|
  {
 | 
						|
    if (lockit)
 | 
						|
      cygheap->fdtab.lock ();
 | 
						|
    if (seed_fd < 0)
 | 
						|
      fd = cygheap->fdtab.find_unused_handle ();
 | 
						|
    else
 | 
						|
      fd = cygheap->fdtab.find_unused_handle (seed_fd + 1);
 | 
						|
    if (fd >= 0)
 | 
						|
      locked = lockit;
 | 
						|
    else
 | 
						|
      {
 | 
						|
	/* errno set by find_unused_handle */
 | 
						|
	if (lockit)
 | 
						|
	  cygheap->fdtab.unlock ();
 | 
						|
	locked = false;
 | 
						|
      }
 | 
						|
  }
 | 
						|
  ~cygheap_fdnew ()
 | 
						|
  {
 | 
						|
    if (cygheap->fdtab[fd])
 | 
						|
      cygheap->fdtab[fd]->inc_refcnt ();
 | 
						|
  }
 | 
						|
  void operator = (fhandler_base *fh) {cygheap->fdtab[fd] = fh;}
 | 
						|
};
 | 
						|
 | 
						|
class cygheap_fdget : public cygheap_fdmanip
 | 
						|
{
 | 
						|
  fhandler_base *fh;
 | 
						|
public:
 | 
						|
  cygheap_fdget (int fd, bool lockit = false, bool do_set_errno = true)
 | 
						|
  {
 | 
						|
    if (lockit)
 | 
						|
      cygheap->fdtab.lock ();
 | 
						|
    if (fd >= 0 && fd < (int) cygheap->fdtab.size && cygheap->fdtab[fd] != NULL)
 | 
						|
      {
 | 
						|
	this->fd = fd;
 | 
						|
	locked = lockit;
 | 
						|
	fh = cygheap->fdtab[fd];
 | 
						|
	fh->inc_refcnt ();
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
	this->fd = -1;
 | 
						|
	if (do_set_errno)
 | 
						|
	  set_errno (EBADF);
 | 
						|
	if (lockit)
 | 
						|
	  cygheap->fdtab.unlock ();
 | 
						|
	locked = false;
 | 
						|
	fh = NULL;
 | 
						|
      }
 | 
						|
  }
 | 
						|
  ~cygheap_fdget ()
 | 
						|
  {
 | 
						|
    if (fh && fh->dec_refcnt () <= 0)
 | 
						|
      {
 | 
						|
	debug_only_printf ("deleting fh %p", fh);
 | 
						|
	delete fh;
 | 
						|
      }
 | 
						|
  }
 | 
						|
  void release () { cygheap->fdtab.release (fd); }
 | 
						|
};
 | 
						|
 | 
						|
class cygheap_fdenum : public cygheap_fdmanip
 | 
						|
{
 | 
						|
 public:
 | 
						|
  cygheap_fdenum (bool lockit = false)
 | 
						|
  {
 | 
						|
    locked = lockit;
 | 
						|
    if (lockit)
 | 
						|
      cygheap->fdtab.lock ();
 | 
						|
    fd = -1;
 | 
						|
  }
 | 
						|
  int next ()
 | 
						|
  {
 | 
						|
    while (++fd < (int) cygheap->fdtab.size)
 | 
						|
      if (cygheap->fdtab[fd] != NULL)
 | 
						|
	return fd;
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  void rewind ()
 | 
						|
  {
 | 
						|
    fd = -1;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
void __stdcall cygheap_fixup_in_child (bool);
 | 
						|
void __stdcall cygheap_init ();
 | 
						|
void setup_cygheap ();
 | 
						|
extern char _cygheap_start[] __attribute__((section(".idata")));
 |