b0e82b74fb
* child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
246 lines
5.5 KiB
C++
246 lines
5.5 KiB
C++
/* registry.cc: registry interface
|
|
|
|
Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
|
|
|
|
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 "winsup.h"
|
|
|
|
char cygnus_class[] = "cygnus";
|
|
|
|
reg_key::reg_key (HKEY top, REGSAM access, ...)
|
|
{
|
|
va_list av;
|
|
va_start (av, access);
|
|
build_reg (top, access, av);
|
|
va_end (av);
|
|
}
|
|
|
|
reg_key::reg_key (REGSAM access, ...)
|
|
{
|
|
va_list av;
|
|
|
|
new (this) reg_key (HKEY_CURRENT_USER, access, "SOFTWARE",
|
|
CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
|
|
CYGWIN_INFO_CYGWIN_REGISTRY_NAME, NULL);
|
|
|
|
HKEY top = key;
|
|
va_start (av, access);
|
|
build_reg (top, KEY_READ, av);
|
|
va_end (av);
|
|
if (top != key)
|
|
RegCloseKey (top);
|
|
}
|
|
|
|
reg_key::reg_key (REGSAM access)
|
|
{
|
|
new (this) reg_key (HKEY_CURRENT_USER, access, "SOFTWARE",
|
|
CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
|
|
CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
|
|
CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, NULL);
|
|
}
|
|
|
|
void
|
|
reg_key::build_reg (HKEY top, REGSAM access, va_list av)
|
|
{
|
|
char *name;
|
|
HKEY r = top;
|
|
key_is_invalid = 0;
|
|
|
|
/* FIXME: Most of the time a valid mount area should exist. Perhaps
|
|
we should just try an open of the correct key first and only resort
|
|
to this method in the unlikely situation that it's the first time
|
|
the current mount areas are being used. */
|
|
|
|
while ((name = va_arg (av, char *)) != NULL)
|
|
{
|
|
DWORD disp;
|
|
int res = RegCreateKeyExA (r,
|
|
name,
|
|
0,
|
|
cygnus_class,
|
|
REG_OPTION_NON_VOLATILE,
|
|
access,
|
|
&sec_none_nih,
|
|
&key,
|
|
&disp);
|
|
if (r != top)
|
|
RegCloseKey (r);
|
|
r = key;
|
|
if (res != ERROR_SUCCESS)
|
|
{
|
|
key_is_invalid = res;
|
|
debug_printf ("failed to create key %s in the registry", name);
|
|
break;
|
|
}
|
|
|
|
/* If we're considering the mounts key, check if it had to
|
|
be created and set had_to_create appropriately. */
|
|
if (strcmp (name, CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME) == 0)
|
|
if (disp == REG_CREATED_NEW_KEY)
|
|
cygwin_shared->mount.had_to_create_mount_areas++;
|
|
}
|
|
}
|
|
|
|
/* Given the current registry key, return the specific int value
|
|
requested. Return def on failure. */
|
|
|
|
int
|
|
reg_key::get_int (const char *name, int def)
|
|
{
|
|
DWORD type;
|
|
DWORD dst;
|
|
DWORD size = sizeof (dst);
|
|
|
|
if (key_is_invalid)
|
|
return def;
|
|
|
|
LONG res = RegQueryValueExA (key, name, 0, &type, (unsigned char *) &dst,
|
|
&size);
|
|
|
|
if (type != REG_DWORD || res != ERROR_SUCCESS)
|
|
return def;
|
|
|
|
return dst;
|
|
}
|
|
|
|
/* Given the current registry key, set a specific int value. */
|
|
|
|
int
|
|
reg_key::set_int (const char *name, int val)
|
|
{
|
|
DWORD value = val;
|
|
if (key_is_invalid)
|
|
return key_is_invalid;
|
|
|
|
return (int) RegSetValueExA (key, name, 0, REG_DWORD,
|
|
(unsigned char *) &value, sizeof (value));
|
|
}
|
|
|
|
/* Given the current registry key, return the specific string value
|
|
requested. Return zero on success, non-zero on failure. */
|
|
|
|
int
|
|
reg_key::get_string (const char *name, char *dst, size_t max, const char * def)
|
|
{
|
|
DWORD size = max;
|
|
DWORD type;
|
|
LONG res;
|
|
|
|
if (key_is_invalid)
|
|
res = key_is_invalid;
|
|
else
|
|
res = RegQueryValueExA (key, name, 0, &type, (unsigned char *) dst, &size);
|
|
|
|
if ((def != 0) && ((type != REG_SZ) || (res != ERROR_SUCCESS)))
|
|
strcpy (dst, def);
|
|
return (int) res;
|
|
}
|
|
|
|
/* Given the current registry key, set a specific string value. */
|
|
|
|
int
|
|
reg_key::set_string (const char *name, const char *src)
|
|
{
|
|
if (key_is_invalid)
|
|
return key_is_invalid;
|
|
return (int) RegSetValueExA (key, name, 0, REG_SZ, (unsigned char*) src,
|
|
strlen (src) + 1);
|
|
}
|
|
|
|
/* Return the handle to key. */
|
|
|
|
HKEY
|
|
reg_key::get_key ()
|
|
{
|
|
return key;
|
|
}
|
|
|
|
/* Delete subkey of current key. Returns the error code from the
|
|
RegDeleteKeyA invocation. */
|
|
|
|
int
|
|
reg_key::kill (const char *name)
|
|
{
|
|
if (key_is_invalid)
|
|
return key_is_invalid;
|
|
return RegDeleteKeyA (key, name);
|
|
}
|
|
|
|
/* Delete the value specified by name of current key. Returns the error code
|
|
from the RegDeleteValueA invocation. */
|
|
|
|
int
|
|
reg_key::killvalue (const char *name)
|
|
{
|
|
if (key_is_invalid)
|
|
return key_is_invalid;
|
|
return RegDeleteValueA (key, name);
|
|
}
|
|
|
|
reg_key::~reg_key ()
|
|
{
|
|
if (!key_is_invalid)
|
|
RegCloseKey (key);
|
|
key_is_invalid = 1;
|
|
}
|
|
|
|
char *
|
|
get_registry_hive_path (const PSID psid, char *path)
|
|
{
|
|
char sid[256];
|
|
char key[256];
|
|
HKEY hkey;
|
|
|
|
if (!psid || !path)
|
|
return NULL;
|
|
convert_sid_to_string_sid (psid, sid);
|
|
strcpy (key,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
|
|
strcat (key, sid);
|
|
if (!RegOpenKeyExA (HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hkey))
|
|
{
|
|
char buf[256];
|
|
DWORD type, siz;
|
|
|
|
key[0] = '\0';
|
|
if (!RegQueryValueExA (hkey, "ProfileImagePath", 0, &type,
|
|
(BYTE *)buf, (siz = 256, &siz)))
|
|
ExpandEnvironmentStringsA (buf, key, 256);
|
|
RegCloseKey (hkey);
|
|
if (key[0])
|
|
return strcpy (path, key);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
load_registry_hive (PSID psid)
|
|
{
|
|
char sid[256];
|
|
char path[MAX_PATH + 1];
|
|
HKEY hkey;
|
|
LONG ret;
|
|
|
|
if (!psid)
|
|
return;
|
|
/* Check if user hive is already loaded. */
|
|
if (!RegOpenKeyExA (HKEY_USERS, convert_sid_to_string_sid (psid, sid),
|
|
0, KEY_READ, &hkey))
|
|
{
|
|
debug_printf ("User registry hive for %s already exists", sid);
|
|
RegCloseKey (hkey);
|
|
return;
|
|
}
|
|
if (get_registry_hive_path (psid, 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);
|
|
}
|
|
}
|
|
|