Bump GPLv2+ to GPLv3+ for some files, clarify BSD 2-clause. Everything else stays under GPLv3+. New Linking Exception exempts resulting executables from LGPLv3 section 4. Add CONTRIBUTORS file to keep track of licensing. Remove 'Copyright Red Hat Inc' comments. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
		
			
				
	
	
		
			212 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* registry.cc: registry interface
 | |
| 
 | |
| 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"
 | |
| #include "registry.h"
 | |
| #include "cygerrno.h"
 | |
| #include "path.h"
 | |
| #include "fhandler.h"
 | |
| #include "dtable.h"
 | |
| #include "cygheap.h"
 | |
| #include "tls_pbuf.h"
 | |
| #include "ntdll.h"
 | |
| #include <wchar.h>
 | |
| 
 | |
| /* 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)
 | |
| {
 | |
|   va_list av;
 | |
|   va_start (av, access);
 | |
|   build_reg (top, access, av);
 | |
|   va_end (av);
 | |
| }
 | |
| 
 | |
| reg_key::reg_key (bool isHKLM, REGSAM access, ...): _disposition (0)
 | |
| {
 | |
|   va_list av;
 | |
|   HANDLE top;
 | |
| 
 | |
|   key_is_invalid = top_key (isHKLM, access, &top);
 | |
|   if (NT_SUCCESS (key_is_invalid))
 | |
|     {
 | |
|       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);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| reg_key::build_reg (HKEY top, REGSAM access, va_list av)
 | |
| {
 | |
|   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;
 | |
|   while ((name = va_arg (av, PWCHAR)) != NULL)
 | |
|     {
 | |
|       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 (!NT_SUCCESS (status))
 | |
| 	{
 | |
| 	  key_is_invalid = status;
 | |
| 	  debug_printf ("failed to create key %S in the registry", &uname);
 | |
| 	  break;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* Given the current registry key, return the specific DWORD value
 | |
|    requested.  Return def on failure. */
 | |
| 
 | |
| DWORD
 | |
| reg_key::get_dword (PCWSTR name, DWORD def)
 | |
| {
 | |
|   if (key_is_invalid)
 | |
|     return def;
 | |
| 
 | |
|   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);
 | |
| 
 | |
|   RtlInitUnicodeString (&uname, name);
 | |
|   status = NtQueryValueKey (key, &uname, KeyValuePartialInformation, vbuf,
 | |
| 			    size, &rsize);
 | |
|   if (status != STATUS_SUCCESS || vbuf->Type != REG_DWORD)
 | |
|     return def;
 | |
|   DWORD *dst = (DWORD *) vbuf->Data;
 | |
|   return *dst;
 | |
| }
 | |
| 
 | |
| /* Given the current registry key, set a specific DWORD value. */
 | |
| 
 | |
| NTSTATUS
 | |
| reg_key::set_dword (PCWSTR name, DWORD val)
 | |
| {
 | |
|   if (key_is_invalid)
 | |
|     return key_is_invalid;
 | |
| 
 | |
|   DWORD value = (DWORD) val;
 | |
|   UNICODE_STRING uname;
 | |
|   RtlInitUnicodeString (&uname, name);
 | |
|   return NtSetValueKey (key, &uname, 0, REG_DWORD, &value, sizeof (value));
 | |
| }
 | |
| 
 | |
| /* Given the current registry key, return the specific string value
 | |
|    requested.  Return zero on success, non-zero on failure. */
 | |
| 
 | |
| NTSTATUS
 | |
| reg_key::get_string (PCWSTR name, PWCHAR dst, size_t max, PCWSTR def)
 | |
| {
 | |
|   NTSTATUS status;
 | |
| 
 | |
|   if (key_is_invalid)
 | |
|     {
 | |
|       status = key_is_invalid;
 | |
|       if (def != NULL)
 | |
| 	wcpncpy (dst, def, max);
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       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);
 | |
| 
 | |
|       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 status;
 | |
| }
 | |
| 
 | |
| /* Given the current registry key, set a specific string value. */
 | |
| 
 | |
| NTSTATUS
 | |
| reg_key::set_string (PCWSTR name, PCWSTR src)
 | |
| {
 | |
|   if (key_is_invalid)
 | |
|     return key_is_invalid;
 | |
| 
 | |
|   UNICODE_STRING uname;
 | |
|   RtlInitUnicodeString (&uname, name);
 | |
|   return NtSetValueKey (key, &uname, 0, REG_SZ, (PVOID) src,
 | |
| 			(wcslen (src) + 1) * sizeof (WCHAR));
 | |
| }
 | |
| 
 | |
| reg_key::~reg_key ()
 | |
| {
 | |
|   if (!key_is_invalid)
 | |
|     NtClose (key);
 | |
|   key_is_invalid = 1;
 | |
| }
 |