From b18cb86be7509b4125732f2b25ff3a6e5f423fa2 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 19 Apr 2011 10:02:06 +0000 Subject: [PATCH] * Makefile.in (DLL_IMPORTS): Drop advapi32.dll. * autoload.cc: Enable autoloading advapi32 functions. * environ.cc (regopt): Use wide char arguments in reg_key functions. * fhandler_console.cc (beep): Ditto. Use WCHAR throughout. * registry.cc (reg_key): Rewrite reg_key class to use native NT registry functions. Use WCHAR string parameters throughout. Use PCWSTR rather than const WCHAR. Drop multibyte char functionality. Drop unused methods. (get_registry_hive_path): Use RtlQueryRegistryValues to fetch path from registry. (load_registry_hive): Drop useless check for user hive being available. Load hive using NtLoadKey. * registry.h: Accommodate above changes. * sched.cc (sched_rr_get_interval): Use wide char arguments in reg_key functions. * shared.cc (init_installation_root): Ditto. (shared_info::init_obcaseinsensitive): Use RtlQueryRegistryValues to fetch obcaseinsensitive value. (shared_info::heap_slop_size): Use wide char arguments in reg_key functions. (shared_info::heap_chunk_size): Ditto. * syscalls.cc (gethostid): Ditto. * winsup.h (__WIDE): Define. (_WIDE): Define. * libc/minires-os-if.c (get_registry_dns_items): Don't fetch values from registry. Just extract them from given UNICODE_STRING parameter. (get_registry_dns): Fetch all registry values at once using RtlQueryRegistryValues. --- winsup/cygwin/ChangeLog | 31 +++ winsup/cygwin/Makefile.in | 2 +- winsup/cygwin/autoload.cc | 4 - winsup/cygwin/environ.cc | 4 +- winsup/cygwin/fhandler_console.cc | 15 +- winsup/cygwin/libc/minires-os-if.c | 89 ++++--- winsup/cygwin/registry.cc | 385 ++++++++++++++--------------- winsup/cygwin/registry.h | 30 +-- winsup/cygwin/sched.cc | 8 +- winsup/cygwin/shared.cc | 35 +-- winsup/cygwin/syscalls.cc | 12 +- winsup/cygwin/winsup.h | 6 + 12 files changed, 322 insertions(+), 299 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 8cf73e8c7..95d7b5267 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,34 @@ +2011-04-19 Corinna Vinschen + + * Makefile.in (DLL_IMPORTS): Drop advapi32.dll. + * autoload.cc: Enable autoloading advapi32 functions. + * environ.cc (regopt): Use wide char arguments in reg_key functions. + * fhandler_console.cc (beep): Ditto. Use WCHAR throughout. + * registry.cc (reg_key): Rewrite reg_key class to use native NT registry + functions. Use WCHAR string parameters throughout. Use PCWSTR rather + than const WCHAR. Drop multibyte char functionality. Drop unused + methods. + (get_registry_hive_path): Use RtlQueryRegistryValues to fetch path from + registry. + (load_registry_hive): Drop useless check for user hive being available. + Load hive using NtLoadKey. + * registry.h: Accommodate above changes. + * sched.cc (sched_rr_get_interval): Use wide char arguments in reg_key + functions. + * shared.cc (init_installation_root): Ditto. + (shared_info::init_obcaseinsensitive): Use RtlQueryRegistryValues to + fetch obcaseinsensitive value. + (shared_info::heap_slop_size): Use wide char arguments in reg_key + functions. + (shared_info::heap_chunk_size): Ditto. + * syscalls.cc (gethostid): Ditto. + * winsup.h (__WIDE): Define. + (_WIDE): Define. + * libc/minires-os-if.c (get_registry_dns_items): Don't fetch values + from registry. Just extract them from given UNICODE_STRING parameter. + (get_registry_dns): Fetch all registry values at once using + RtlQueryRegistryValues. + 2011-04-19 Corinna Vinschen * net.cc (get_ipv4fromreg_ipcnt): Rearrange to fetch all registry diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index f29c1dd1c..ee6f251c2 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -130,7 +130,7 @@ EXTRA_OFILES:= MALLOC_OFILES:=@MALLOC_OFILES@ -DLL_IMPORTS:=$(w32api_lib)/libadvapi32.a $(w32api_lib)/libkernel32.a $(w32api_lib)/libntdll.a +DLL_IMPORTS:=$(w32api_lib)/libkernel32.a $(w32api_lib)/libntdll.a MT_SAFE_OBJECTS:= # Please maintain this list in sorted order, with maximum files per 86 col line diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 53812e06b..55d1c46c4 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -352,9 +352,6 @@ wsock_init () LoadDLLprime (ws2_32, _wsock_init, 0) -#if 0 -/* Don't enable until libadvapi32.a has been removed from DLL_IMPORTS, - otherwise mintty will stop working on pre-Vista for some reason. */ LoadDLLfunc (CreateProcessAsUserW, 44, advapi32) LoadDLLfunc (CryptAcquireContextW, 20, advapi32) LoadDLLfunc (CryptGenRandom, 12, advapi32) @@ -381,7 +378,6 @@ LoadDLLfunc (RegQueryInfoKeyW, 48, advapi32) LoadDLLfunc (RegQueryValueExW, 24, advapi32) LoadDLLfunc (RegisterEventSourceW, 8, advapi32) LoadDLLfunc (ReportEventW, 36, advapi32) -#endif LoadDLLfunc (DnsQuery_A, 24, dnsapi) LoadDLLfunc (DnsRecordListFree, 8, dnsapi) diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 9d1544429..15fbb079d 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -2,7 +2,7 @@ process's environment. Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for @@ -710,7 +710,7 @@ regopt (const WCHAR *name, char *buf) for (int i = 0; i < 2; i++) { - reg_key r (i, KEY_READ, CYGWIN_INFO_PROGRAM_OPTIONS_NAME, NULL); + reg_key r (i, KEY_READ, _WIDE (CYGWIN_INFO_PROGRAM_OPTIONS_NAME), NULL); if (r.get_string (lname.Buffer, (PWCHAR) buf, NT_MAX_PATH, L"") == ERROR_SUCCESS) { diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index b40244b15..8ce82e481 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -61,16 +61,17 @@ dev_console NO_COPY *fhandler_console::dev_state; static void beep () { - reg_key r (HKEY_CURRENT_USER, KEY_ALL_ACCESS, "AppEvents", "Schemes", "Apps", - ".Default", ".Default", ".Current", NULL); + const WCHAR ding[] = L"\\media\\ding.wav"; + reg_key r (HKEY_CURRENT_USER, KEY_ALL_ACCESS, L"AppEvents", L"Schemes", + L"Apps", L".Default", L".Default", L".Current", NULL); if (r.created ()) { - char *buf = NULL; - UINT len = GetWindowsDirectory (buf, 0); - buf = (char *) alloca (len += sizeof ("\\media\\ding.wav")); - UINT res = GetWindowsDirectory (buf, len); + PWCHAR buf = NULL; + UINT len = GetWindowsDirectoryW (buf, 0) * sizeof (WCHAR); + buf = (PWCHAR) alloca (len += sizeof (ding)); + UINT res = GetWindowsDirectoryW (buf, len); if (res && res <= len) - r.set_string ("", strcat (buf, "\\media\\ding.wav")); + r.set_string (L"", wcscat (buf, ding)); } MessageBeep (MB_OK); } diff --git a/winsup/cygwin/libc/minires-os-if.c b/winsup/cygwin/libc/minires-os-if.c index 3715c0847..eb788f2c6 100644 --- a/winsup/cygwin/libc/minires-os-if.c +++ b/winsup/cygwin/libc/minires-os-if.c @@ -1,6 +1,6 @@ /* minires-os-if.c. Stub synchronous resolver for Cygwin. - Copyright 2006, 2007, 2008, 2009 Red Hat, Inc. + Copyright 2006, 2007, 2008, 2009, 2011 Red Hat, Inc. Written by Pierre A. Humblet @@ -27,6 +27,9 @@ details. */ #include #include #include +#include +#include "ntdll.h" +#include /*********************************************************************** * write_record: Translates a Windows DNS record into a compressed record @@ -291,36 +294,25 @@ done: * get_registry_items: returns dns items from the registry - kHey: Handle to registry key - KeyValue: key value to read + in: Unicode representation of registry value "value". what: 0 addresses ; 1 search list ***********************************************************************/ -static void get_registry_dns_items(HKEY hKey, LPCTSTR KeyValue, - res_state statp, int what) +static void get_registry_dns_items(PUNICODE_STRING in, res_state statp, + int what) { - DWORD size = 0; - LONG res; - LPBYTE list; int debug = statp->options & RES_DEBUG; - res = RegQueryValueEx( hKey, KeyValue, NULL, NULL, NULL, &size); - DPRINTF(debug, "value %s, error %lu (Windows), size %lu\n", - KeyValue, res, size); - if ((res == ERROR_SUCCESS) && (size > 1)) { - if (!(list = (LPBYTE) alloca(size))) { - DPRINTF(debug, "alloca: %s\n", strerror(errno)); - } - else if ((res = RegQueryValueEx( hKey, KeyValue, NULL, NULL, list, - &size )) != ERROR_SUCCESS) { - DPRINTF(debug, "RegQueryValueEx: error %lu (Windows)\n", res); - } - else if (what == 0) { /* Get the addresses */ - BYTE *ap, *srch; + if (in->Length) { + char list[in->Length]; + size_t size = wcstombs (list, in->Buffer, in->Length); + if (what == 0) { /* Get the addresses */ + char *ap, *srch; int numAddresses = 0; for (ap = list; ap < list + size && *ap; ap = srch) { /* The separation character can be 0, ' ', or ','. */ - for (srch = ap; *srch && (isdigit(*srch) || *srch == '.' ); srch++); + for (srch = ap; *srch && (isdigit((unsigned) *srch) || *srch == '.' ); + srch++); *srch++ = 0; if (numAddresses < DIM(statp->nsaddr_list)) { DPRINTF(debug, "server \"%s\"\n", ap); @@ -334,7 +326,7 @@ static void get_registry_dns_items(HKEY hKey, LPCTSTR KeyValue, statp->nscount = numAddresses; } else /* Parse the search line */ - minires_get_search((char *) list, statp); + minires_get_search(list, statp); } return; } @@ -351,25 +343,52 @@ static void get_registry_dns_items(HKEY hKey, LPCTSTR KeyValue, static void get_registry_dns(res_state statp) { - HKEY hKey; - DWORD res; - const char *keyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + NTSTATUS status; + const PCWSTR keyName = L"Tcpip\\Parameters"; DPRINTF(statp->options & RES_DEBUG, "key %s\n", keyName); - if ((res = RegOpenKeyEx( HKEY_LOCAL_MACHINE, keyName, 0, - KEY_QUERY_VALUE | KEY_READ, &hKey)) != ERROR_SUCCESS) { - DPRINTF(statp->options & RES_DEBUG, "RegOpenKeyEx: error %lu (Windows)\n", res); - return; - } + status = RtlCheckRegistryKey (RTL_REGISTRY_SERVICES, keyName); + if (!NT_SUCCESS (status)) + { + DPRINTF (statp->options & RES_DEBUG, "RtlCheckRegistryKey: status %p\n", + status); + return; + } + + UNICODE_STRING uns = { 0, 0, NULL }; + UNICODE_STRING udns = { 0, 0, NULL }; + UNICODE_STRING usl = { 0, 0, NULL }; + RTL_QUERY_REGISTRY_TABLE tab[4] = { + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND, + L"NameServer", &uns, REG_NONE, NULL, 0 }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND, + L"DhcpNameServer", &udns, REG_NONE, NULL, 0 }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND, + L"SearchList", &usl, REG_NONE, NULL, 0 }, + }; + + status = RtlQueryRegistryValues (RTL_REGISTRY_SERVICES, keyName, tab, + NULL, NULL); + if (!NT_SUCCESS (status)) + { + DPRINTF (statp->options & RES_DEBUG, + "RtlQueryRegistryValues: status %p\n", status); + return; + } if (statp->nscount == 0) - get_registry_dns_items(hKey, "NameServer", statp, 0); + get_registry_dns_items(&uns, statp, 0); if (statp->nscount == 0) - get_registry_dns_items(hKey, "DhcpNameServer", statp, 0); + get_registry_dns_items(&udns, statp, 0); if (statp->dnsrch[0] == NULL) - get_registry_dns_items(hKey, "SearchList", statp, 1); + get_registry_dns_items(&usl, statp, 1); - RegCloseKey(hKey); + if (uns.Buffer) + RtlFreeUnicodeString (&uns); + if (udns.Buffer) + RtlFreeUnicodeString (&udns); + if (usl.Buffer) + RtlFreeUnicodeString (&usl); return; } diff --git a/winsup/cygwin/registry.cc b/winsup/cygwin/registry.cc index 5f65603d8..913f5d839 100644 --- a/winsup/cygwin/registry.cc +++ b/winsup/cygwin/registry.cc @@ -1,7 +1,7 @@ /* registry.cc: registry interface Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. + 2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. This file is part of Cygwin. @@ -17,7 +17,45 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "tls_pbuf.h" +#include "ntdll.h" #include +#include + +/* Opens a key under the appropriate Cygwin key. + Do not use HKCU per MS KB 199190 */ +static NTSTATUS +top_key (bool isHKLM, REGSAM access, PHANDLE top) +{ + WCHAR rbuf[PATH_MAX], *p; + UNICODE_STRING rpath; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + + InitializeObjectAttributes (&attr, &rpath, OBJ_CASE_INSENSITIVE, NULL, NULL); + if (isHKLM) + { + wcpcpy (rbuf, L"\\Registry\\Machine"); + RtlInitUnicodeString (&rpath, rbuf); + status = NtOpenKey (top, access, &attr); + } + else + { + WCHAR name[128]; + PCWSTR names[2] = {cygheap->user.get_windows_id (name), + L".DEFAULT"}; + + p = wcpcpy (rbuf, L"\\Registry\\User\\"); + for (int i = 0; i < 2; i++) + { + wcpcpy (p, names[i]); + RtlInitUnicodeString (&rpath, rbuf); + status = NtOpenKey (top, access, &attr); + if (NT_SUCCESS (status)) + break; + } + } + return status; +} reg_key::reg_key (HKEY top, REGSAM access, ...): _disposition (0) { @@ -27,75 +65,57 @@ reg_key::reg_key (HKEY top, REGSAM access, ...): _disposition (0) va_end (av); } -/* Opens a key under the appropriate Cygwin key. - Do not use HKCU per MS KB 199190 */ - reg_key::reg_key (bool isHKLM, REGSAM access, ...): _disposition (0) { va_list av; - HKEY top; + HANDLE top; - if (isHKLM) - top = HKEY_LOCAL_MACHINE; - else + key_is_invalid = top_key (isHKLM, access, &top); + if (NT_SUCCESS (key_is_invalid)) { - char name[128]; - const char *names[2] = {cygheap->user.get_windows_id (name), ".DEFAULT"}; - for (int i = 0; i < 2; i++) - { - key_is_invalid = RegOpenKeyEx (HKEY_USERS, names[i], 0, access, &top); - if (key_is_invalid == ERROR_SUCCESS) - goto OK; - debug_printf ("HKU\\%s failed, Win32 error %ld", names[i], key_is_invalid); - } - return; + new (this) reg_key ((HKEY) top, access, L"SOFTWARE", + _WIDE (CYGWIN_INFO_CYGWIN_REGISTRY_NAME), NULL); + NtClose (top); + if (key_is_invalid) + return; + top = key; + va_start (av, access); + build_reg ((HKEY) top, access, av); + va_end (av); + if (top != key) + NtClose (top); } -OK: - new (this) reg_key (top, access, "SOFTWARE", - CYGWIN_INFO_CYGWIN_REGISTRY_NAME, NULL); - if (top != HKEY_LOCAL_MACHINE) - RegCloseKey (top); - if (key_is_invalid) - return; - - top = key; - va_start (av, access); - build_reg (top, access, av); - va_end (av); - if (top != key) - RegCloseKey (top); } void reg_key::build_reg (HKEY top, REGSAM access, va_list av) { - char *name; - HKEY r = top; + PWCHAR name; + HANDLE r; + UNICODE_STRING uname; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + + if (top != HKEY_LOCAL_MACHINE && top != HKEY_CURRENT_USER) + r = (HANDLE) top; + else if (!NT_SUCCESS (top_key (top == HKEY_LOCAL_MACHINE, access, &r))) + return; 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) + while ((name = va_arg (av, PWCHAR)) != NULL) { - int res = RegCreateKeyExA (r, - name, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - access, - &sec_none_nih, - &key, - &_disposition); - if (r != top) - RegCloseKey (r); + RtlInitUnicodeString (&uname, name); + InitializeObjectAttributes (&attr, &uname, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, r, NULL); + + status = NtCreateKey (&key, access, &attr, 0, NULL, + REG_OPTION_NON_VOLATILE, &_disposition); + if (r != (HANDLE) top) + NtClose (r); r = key; - if (res != ERROR_SUCCESS) + if (!NT_SUCCESS (status)) { - key_is_invalid = res; - debug_printf ("failed to create key %s in the registry", name); + key_is_invalid = status; + debug_printf ("failed to create key %S in the registry", uname); break; } } @@ -105,209 +125,164 @@ reg_key::build_reg (HKEY top, REGSAM access, va_list av) requested. Return def on failure. */ int -reg_key::get_int (const char *name, int def) +reg_key::get_int (PCWSTR name, int def) { - DWORD type; - DWORD dst; - DWORD size = sizeof (dst); - if (key_is_invalid) return def; - LONG res = RegQueryValueExA (key, name, 0, &type, (LPBYTE) &dst, &size); + NTSTATUS status; + UNICODE_STRING uname; + ULONG size = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + sizeof (DWORD); + ULONG rsize; + PKEY_VALUE_PARTIAL_INFORMATION vbuf = (PKEY_VALUE_PARTIAL_INFORMATION) + alloca (size); - if (type != REG_DWORD || res != ERROR_SUCCESS) + RtlInitUnicodeString (&uname, name); + status = NtQueryValueKey (key, &uname, KeyValuePartialInformation, vbuf, + size, &rsize); + if (status != STATUS_SUCCESS || vbuf->Type != REG_DWORD) return def; - - return dst; -} - -int -reg_key::get_int (const WCHAR *name, int def) -{ - DWORD type; - DWORD dst; - DWORD size = sizeof (dst); - - if (key_is_invalid) - return def; - - LONG res = RegQueryValueExW (key, name, 0, &type, (LPBYTE) &dst, &size); - - if (type != REG_DWORD || res != ERROR_SUCCESS) - return def; - - return dst; + DWORD dst = *(DWORD *) vbuf->Data; + return (int) dst; } /* Given the current registry key, set a specific int value. */ int -reg_key::set_int (const char *name, int val) +reg_key::set_int (PCWSTR name, int val) { - DWORD value = val; if (key_is_invalid) return key_is_invalid; - return (int) RegSetValueExA (key, name, 0, REG_DWORD, - (const BYTE *) &value, sizeof (value)); -} - -int -reg_key::set_int (const PWCHAR name, int val) -{ - DWORD value = val; - if (key_is_invalid) - return key_is_invalid; - - return (int) RegSetValueExW (key, name, 0, REG_DWORD, - (const BYTE *) &value, sizeof (value)); + DWORD value = (DWORD) val; + UNICODE_STRING uname; + RtlInitUnicodeString (&uname, name); + NTSTATUS status = NtSetValueKey (key, &uname, 0, REG_DWORD, + &value, sizeof (value)); + return (int) status; } /* 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) +reg_key::get_string (PCWSTR name, PWCHAR dst, size_t max, PCWSTR def) { - DWORD size = max; - DWORD type; - LONG res; + NTSTATUS status; if (key_is_invalid) - res = key_is_invalid; + { + status = key_is_invalid; + if (def != NULL) + wcpncpy (dst, def, max); + } else - res = RegQueryValueExA (key, name, 0, &type, (LPBYTE) dst, &size); + { + UNICODE_STRING uname; + ULONG size = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + max * sizeof (WCHAR); + ULONG rsize; + PKEY_VALUE_PARTIAL_INFORMATION vbuf = (PKEY_VALUE_PARTIAL_INFORMATION) + alloca (size); - if ((def != 0) && ((type != REG_SZ) || (res != ERROR_SUCCESS))) - strcpy (dst, def); - return (int) res; -} - -int -reg_key::get_string (const WCHAR *name, PWCHAR dst, size_t max, const WCHAR *def) -{ - DWORD size = max; - DWORD type; - LONG res; - - if (key_is_invalid) - res = key_is_invalid; - else - res = RegQueryValueExW (key, name, 0, &type, (LPBYTE) dst, &size); - - if ((def != 0) && ((type != REG_SZ) || (res != ERROR_SUCCESS))) - wcscpy (dst, def); - return (int) res; + RtlInitUnicodeString (&uname, name); + status = NtQueryValueKey (key, &uname, KeyValuePartialInformation, vbuf, + size, &rsize); + if (status != STATUS_SUCCESS || vbuf->Type != REG_SZ) + wcpncpy (dst, def, max); + else + wcpncpy (dst, (PWCHAR) vbuf->Data, max); + + } + return (int) status; } /* Given the current registry key, set a specific string value. */ int -reg_key::set_string (const char *name, const char *src) +reg_key::set_string (PCWSTR name, PCWSTR src) { if (key_is_invalid) return key_is_invalid; - return (int) RegSetValueExA (key, name, 0, REG_SZ, (const BYTE*) src, - strlen (src) + 1); -} -int -reg_key::set_string (const PWCHAR name, const PWCHAR src) -{ - if (key_is_invalid) - return key_is_invalid; - return (int) RegSetValueExW (key, name, 0, REG_SZ, (const BYTE*) src, - (wcslen (src) + 1) * sizeof (WCHAR)); -} - -/* 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); + UNICODE_STRING uname; + RtlInitUnicodeString (&uname, name); + NTSTATUS status = NtSetValueKey (key, &uname, 0, REG_SZ, (PVOID) src, + (wcslen (src) + 1) * sizeof (WCHAR)); + return (int) status; } reg_key::~reg_key () { if (!key_is_invalid) - RegCloseKey (key); + NtClose (key); key_is_invalid = 1; } PWCHAR -get_registry_hive_path (const PWCHAR name, PWCHAR path) +get_registry_hive_path (PCWSTR name, PWCHAR path) { - WCHAR key[256], *kend; - HKEY hkey; - if (!name || !path) return NULL; - kend = wcpcpy (key, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"); - wcpcpy (kend, name); - if (!RegOpenKeyExW (HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hkey)) - { - tmp_pathbuf tp; - PWCHAR buf = tp.w_get (); - DWORD type, siz; - path[0] = L'\0'; - if (!RegQueryValueExW (hkey, L"ProfileImagePath", 0, &type, - (BYTE *)buf, (siz = NT_MAX_PATH, &siz))) - ExpandEnvironmentStringsW (buf, path, NT_MAX_PATH); - RegCloseKey (hkey); - if (path[0]) - return path; + WCHAR key[256]; + UNICODE_STRING buf; + tmp_pathbuf tp; + tp.u_get (&buf); + NTSTATUS status; + + RTL_QUERY_REGISTRY_TABLE tab[2] = { + { NULL, RTL_QUERY_REGISTRY_NOEXPAND | RTL_QUERY_REGISTRY_DIRECT + | RTL_QUERY_REGISTRY_REQUIRED, + L"ProfileImagePath", &buf, REG_NONE, NULL, 0 }, + { NULL, 0, NULL, NULL, 0, NULL, 0 } + }; + wcpcpy (wcpcpy (key, L"ProfileList\\"), name); + status = RtlQueryRegistryValues (RTL_REGISTRY_WINDOWS_NT, key, tab, + NULL, NULL); + if (!NT_SUCCESS (status) || buf.Length == 0) + { + system_printf ("ProfileImagePath for %W not found, status %p", name, + status); + return NULL; } - debug_printf ("HKLM\\%W not found", key); - return NULL; + wcpcpy (path, L"\\??\\"); + ExpandEnvironmentStringsW (buf.Buffer, path + 4, NT_MAX_PATH - 4); + system_printf ("ProfileImagePath for %W: %W", name, path); + return path; } void -load_registry_hive (const PWCHAR name) +load_registry_hive (PCWSTR name) { - tmp_pathbuf tp; - PWCHAR path = tp.w_get (); - HKEY hkey; - LONG ret; - if (!name) return; - /* Check if user hive is already loaded. */ - if (!RegOpenKeyExW (HKEY_USERS, name, 0, KEY_READ, &hkey)) - { - debug_printf ("User registry hive for %W already exists", name); - RegCloseKey (hkey); - return; - } - if (get_registry_hive_path (name, path)) - { - wcscat (path, L"\\NTUSER.DAT"); - if ((ret = RegLoadKeyW (HKEY_USERS, name, path)) != ERROR_SUCCESS) - debug_printf ("Loading user registry hive for %W failed: %d", name, ret); - } -} + /* Fetch the path. */ + tmp_pathbuf tp; + PWCHAR path = tp.w_get (); + if (!get_registry_hive_path (name, path)) + return; + + WCHAR key[256]; + UNICODE_STRING ukey, upath; + OBJECT_ATTRIBUTES key_attr, path_attr; + NTSTATUS status; + + /* Create the object attributes for key and path. */ + wcpcpy (wcpcpy (key, L"\\Registry\\User\\"), name); + RtlInitUnicodeString (&ukey, key); + InitializeObjectAttributes (&key_attr, &ukey, OBJ_CASE_INSENSITIVE, + NULL, NULL); + wcscat (path, L"\\NTUSER.DAT"); + RtlInitUnicodeString (&upath, path); + InitializeObjectAttributes (&path_attr, &upath, OBJ_CASE_INSENSITIVE, + NULL, NULL); + /* Load file into key. */ + status = NtLoadKey (&key_attr, &path_attr); + if (!NT_SUCCESS (status)) + system_printf ("Loading user registry hive %S into %S failed: %p", + &upath, &ukey, status); + else + system_printf ("Loading user registry hive %S into %S SUCCEEDED: %p", + &upath, &ukey, status); +} diff --git a/winsup/cygwin/registry.h b/winsup/cygwin/registry.h index 2b0f4657a..640998a3b 100644 --- a/winsup/cygwin/registry.h +++ b/winsup/cygwin/registry.h @@ -1,6 +1,7 @@ /* registry.h: shared info for cygwin - Copyright 2000, 2001, 2004, 2006, 2008 Red Hat, Inc. + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010, 2011 Red Hat, Inc. This file is part of Cygwin. @@ -12,8 +13,8 @@ class reg_key { private: - HKEY key; - LONG key_is_invalid; + HANDLE key; + NTSTATUS key_is_invalid; DWORD _disposition; public: @@ -24,22 +25,13 @@ public: void *operator new (size_t, void *p) {return p;} void build_reg (HKEY key, REGSAM access, va_list av); - int error () {return key == (HKEY) INVALID_HANDLE_VALUE;} + int error () {return key == NULL;} - int kill (const char *child); - int killvalue (const char *name); + int get_int (PCWSTR, int); + int get_string (PCWSTR, PWCHAR, size_t, PCWSTR); - HKEY get_key (); - - int get_int (const char *, int); - int get_int (const WCHAR *, int); - int get_string (const char *, char *, size_t, const char *); - int get_string (const WCHAR *, PWCHAR, size_t, const WCHAR *); - - int set_int (const char *, int); - int set_int (const PWCHAR, int); - int set_string (const char *, const char *); - int set_string (const PWCHAR, const PWCHAR); + int set_int (PCWSTR, int); + int set_string (PCWSTR, PCWSTR); bool created () const {return _disposition & REG_CREATED_NEW_KEY;} @@ -47,5 +39,5 @@ public: }; /* Evaluates path to the directory of the local user registry hive */ -PWCHAR __stdcall get_registry_hive_path (const PWCHAR name, PWCHAR path); -void __stdcall load_registry_hive (const PWCHAR name); +PWCHAR __stdcall get_registry_hive_path (PCWSTR name, PWCHAR path); +void __stdcall load_registry_hive (PCWSTR name); diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc index eae493b3a..69b7a4667 100644 --- a/winsup/cygwin/sched.cc +++ b/winsup/cygwin/sched.cc @@ -1,6 +1,6 @@ /* sched.cc: scheduler interface for Cygwin - Copyright 2001, 2002, 2006, 2007 Red Hat, Inc. + Copyright 2001, 2003, 2006, 2008, 2011 Red Hat, Inc. Written by Robert Collins @@ -271,14 +271,14 @@ sched_rr_get_interval (pid_t pid, struct timespec *interval) else forprocid = 0; - reg_key reg (HKEY_LOCAL_MACHINE, KEY_READ, "SYSTEM", "CurrentControlSet", - "Control", "PriorityControl", NULL); + reg_key reg (HKEY_LOCAL_MACHINE, KEY_READ, L"SYSTEM", L"CurrentControlSet", + L"Control", L"PriorityControl", NULL); if (reg.error ()) { set_errno (ESRCH); return -1; } - prisep = reg.get_int ("Win32PrioritySeparation", 2); + prisep = reg.get_int (L"Win32PrioritySeparation", 2); pinfo pi (pid ? pid : myself->pid); if (!pi) { diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index 10d03b088..0b19b188d 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -1,7 +1,7 @@ /* shared.cc: shared data area support. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. This file is part of Cygwin. @@ -109,7 +109,8 @@ init_installation_root () for (int i = 1; i >= 0; --i) { - reg_key r (i, KEY_WRITE, CYGWIN_INFO_INSTALLATIONS_NAME, NULL); + reg_key r (i, KEY_WRITE, _WIDE (CYGWIN_INFO_INSTALLATIONS_NAME), + NULL); if (r.set_string (installation_key_buf, installation_root) == ERROR_SUCCESS) break; @@ -370,19 +371,19 @@ shared_destroy () void shared_info::init_obcaseinsensitive () { - HKEY key; - DWORD size = sizeof (DWORD); - - obcaseinsensitive = 1; - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, - "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\kernel", - 0, KEY_READ, &key) == ERROR_SUCCESS) - { - RegQueryValueEx (key, "obcaseinsensitive", NULL, NULL, - (LPBYTE) &obcaseinsensitive, &size); - RegCloseKey (key); - } - debug_printf ("obcaseinsensitive set to %d", obcaseinsensitive); + NTSTATUS status; + DWORD def_obcaseinsensitive = 1; + + obcaseinsensitive = def_obcaseinsensitive; + RTL_QUERY_REGISTRY_TABLE tab[2] = { + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOSTRING, + L"obcaseinsensitive", &obcaseinsensitive, REG_DWORD, + &def_obcaseinsensitive, sizeof (DWORD) }, + { NULL, 0, NULL, NULL, 0, NULL, 0 } + }; + status = RtlQueryRegistryValues (RTL_REGISTRY_CONTROL, + L"Session Manager\\kernel", + tab, NULL, NULL); } void inline @@ -449,7 +450,7 @@ shared_info::heap_slop_size () { reg_key reg (i, KEY_READ, NULL); - if ((heap_slop = reg.get_int ("heap_slop_in_mb", 0))) + if ((heap_slop = reg.get_int (L"heap_slop_in_mb", 0))) break; heap_slop = wincap.heapslop (); } @@ -475,7 +476,7 @@ shared_info::heap_chunk_size () /* FIXME: We should not be restricted to a fixed size heap no matter what the fixed size is. */ - if ((heap_chunk = reg.get_int ("heap_chunk_in_mb", 0))) + if ((heap_chunk = reg.get_int (L"heap_chunk_in_mb", 0))) break; heap_chunk = 384; /* Default */ } diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index a11142b2d..c05c58798 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -3682,8 +3682,8 @@ updwtmpx (const char *wtmpx_file, const struct utmpx *utmpx) updwtmp (wtmpx_file, (const struct utmp *) utmpx); } -extern "C" -long gethostid (void) +extern "C" long +gethostid (void) { unsigned data[13] = {0x92895012, 0x10293412, @@ -3766,9 +3766,11 @@ long gethostid (void) else debug_printf ("no Ethernet card installed"); - reg_key key (HKEY_LOCAL_MACHINE, KEY_READ, "SOFTWARE", "Microsoft", - "Windows NT", "CurrentVersion", NULL); - key.get_string ("ProductId", (char *)&data[6], 24, "00000-000-0000000-00000"); + WCHAR wdata[24]; + reg_key key (HKEY_LOCAL_MACHINE, KEY_READ, L"SOFTWARE", L"Microsoft", + L"Windows NT", L"CurrentVersion", NULL); + key.get_string (L"ProductId", wdata, 24, L"00000-000-0000000-00000"); + sys_wcstombs ((char *)&data[6], 24, wdata, 24); debug_printf ("Windows Product ID: %s", (char *)&data[6]); GetDiskFreeSpaceEx ("C:\\", NULL, (PULARGE_INTEGER) &data[11], NULL); diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 848967866..087da61f4 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -70,6 +70,12 @@ int fcntl64 (int fd, int cmd, ...); application provided path strings we handle. */ #define NT_MAX_PATH 32768 +/* This definition allows to define wide char strings using macros as + parameters. See the definition of __CONCAT in newlib's sys/cdefs.h + and accompanying comment. */ +#define __WIDE(a) L ## a +#define _WIDE(a) __WIDE(a) + #ifdef __cplusplus extern const char case_folded_lower[];