1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
/* 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;
}
|