ReactOS 0.4.15-dev-7924-g5949c20
registry.c
Go to the documentation of this file.
1/* Copyright (c) Mark Harmstone 2016-17
2 *
3 * This file is part of WinBtrfs.
4 *
5 * WinBtrfs is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public Licence as published by
7 * the Free Software Foundation, either version 3 of the Licence, or
8 * (at your option) any later version.
9 *
10 * WinBtrfs is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public Licence for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public Licence
16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "btrfs_drv.h"
19#include "zstd/zstd.h"
20
24
25#ifdef _DEBUG
26extern HANDLE log_handle;
27extern ERESOURCE log_lock;
28extern PFILE_OBJECT comfo;
29extern PDEVICE_OBJECT comdo;
30#endif
31
33
34static const WCHAR option_mounted[] = L"Mounted";
35
37 BTRFS_UUID* uuid = &Vcb->superblock.uuid;
38 mount_options* options = &Vcb->options;
39 UNICODE_STRING path, ignoreus, compressus, compressforceus, compresstypeus, readonlyus, zliblevelus, flushintervalus,
40 maxinlineus, subvolidus, skipbalanceus, nobarrierus, notrimus, clearcacheus, allowdegradedus, zstdlevelus,
41 norootdirus, nodatacowus;
44 ULONG i, j, kvfilen, index, retlen;
46 HANDLE h;
47
48 options->compress = mount_compress;
49 options->compress_force = mount_compress_force;
51 options->readonly = mount_readonly;
52 options->zlib_level = mount_zlib_level;
53 options->zstd_level = mount_zstd_level;
54 options->flush_interval = mount_flush_interval;
55 options->max_inline = min(mount_max_inline, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - sizeof(EXTENT_DATA) + 1);
56 options->skip_balance = mount_skip_balance;
57 options->no_barrier = mount_no_barrier;
58 options->no_trim = mount_no_trim;
59 options->clear_cache = mount_clear_cache;
60 options->allow_degraded = mount_allow_degraded;
61 options->subvol_id = 0;
62 options->no_root_dir = mount_no_root_dir;
63 options->nodatacow = mount_nodatacow;
64
65 path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
67
68 if (!path.Buffer) {
69 ERR("out of memory\n");
71 }
72
74 i = registry_path.Length / sizeof(WCHAR);
75
76 path.Buffer[i] = '\\';
77 i++;
78
79 for (j = 0; j < 16; j++) {
80 path.Buffer[i] = hex_digit((uuid->uuid[j] & 0xF0) >> 4);
81 path.Buffer[i+1] = hex_digit(uuid->uuid[j] & 0xF);
82
83 i += 2;
84
85 if (j == 3 || j == 5 || j == 7 || j == 9) {
86 path.Buffer[i] = '-';
87 i++;
88 }
89 }
90
91 kvfilen = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR) + (255 * sizeof(WCHAR));
93 if (!kvfi) {
94 ERR("out of memory\n");
96 goto end;
97 }
98
100
101 Status = ZwOpenKey(&h, KEY_QUERY_VALUE, &oa);
104 goto end;
105 } else if (!NT_SUCCESS(Status)) {
106 ERR("ZwOpenKey returned %08lx\n", Status);
107 goto end;
108 }
109
110 index = 0;
111
112 RtlInitUnicodeString(&ignoreus, L"Ignore");
113 RtlInitUnicodeString(&compressus, L"Compress");
114 RtlInitUnicodeString(&compressforceus, L"CompressForce");
115 RtlInitUnicodeString(&compresstypeus, L"CompressType");
116 RtlInitUnicodeString(&readonlyus, L"Readonly");
117 RtlInitUnicodeString(&zliblevelus, L"ZlibLevel");
118 RtlInitUnicodeString(&flushintervalus, L"FlushInterval");
119 RtlInitUnicodeString(&maxinlineus, L"MaxInline");
120 RtlInitUnicodeString(&subvolidus, L"SubvolId");
121 RtlInitUnicodeString(&skipbalanceus, L"SkipBalance");
122 RtlInitUnicodeString(&nobarrierus, L"NoBarrier");
123 RtlInitUnicodeString(&notrimus, L"NoTrim");
124 RtlInitUnicodeString(&clearcacheus, L"ClearCache");
125 RtlInitUnicodeString(&allowdegradedus, L"AllowDegraded");
126 RtlInitUnicodeString(&zstdlevelus, L"ZstdLevel");
127 RtlInitUnicodeString(&norootdirus, L"NoRootDir");
128 RtlInitUnicodeString(&nodatacowus, L"NoDataCOW");
129
130 do {
131 Status = ZwEnumerateValueKey(h, index, KeyValueFullInformation, kvfi, kvfilen, &retlen);
132
133 index++;
134
135 if (NT_SUCCESS(Status)) {
137
138 us.Length = us.MaximumLength = (USHORT)kvfi->NameLength;
139 us.Buffer = kvfi->Name;
140
141 if (FsRtlAreNamesEqual(&ignoreus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
142 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
143
144 options->ignore = *val != 0 ? true : false;
145 } else if (FsRtlAreNamesEqual(&compressus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
146 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
147
148 options->compress = *val != 0 ? true : false;
149 } else if (FsRtlAreNamesEqual(&compressforceus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
150 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
151
152 options->compress_force = *val != 0 ? true : false;
153 } else if (FsRtlAreNamesEqual(&compresstypeus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
154 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
155
156 options->compress_type = (uint8_t)(*val > BTRFS_COMPRESSION_ZSTD ? 0 : *val);
157 } else if (FsRtlAreNamesEqual(&readonlyus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
158 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
159
160 options->readonly = *val != 0 ? true : false;
161 } else if (FsRtlAreNamesEqual(&zliblevelus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
162 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
163
164 options->zlib_level = *val;
165 } else if (FsRtlAreNamesEqual(&flushintervalus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
166 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
167
168 options->flush_interval = *val;
169 } else if (FsRtlAreNamesEqual(&maxinlineus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
170 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
171
172 options->max_inline = min(*val, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - sizeof(EXTENT_DATA) + 1);
173 } else if (FsRtlAreNamesEqual(&subvolidus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_QWORD) {
174 uint64_t* val = (uint64_t*)((uint8_t*)kvfi + kvfi->DataOffset);
175
176 options->subvol_id = *val;
177 } else if (FsRtlAreNamesEqual(&skipbalanceus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
178 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
179
180 options->skip_balance = *val;
181 } else if (FsRtlAreNamesEqual(&nobarrierus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
182 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
183
184 options->no_barrier = *val;
185 } else if (FsRtlAreNamesEqual(&notrimus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
186 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
187
188 options->no_trim = *val;
189 } else if (FsRtlAreNamesEqual(&clearcacheus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
190 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
191
192 options->clear_cache = *val;
193 } else if (FsRtlAreNamesEqual(&allowdegradedus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
194 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
195
196 options->allow_degraded = *val;
197 } else if (FsRtlAreNamesEqual(&zstdlevelus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
198 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
199
200 options->zstd_level = *val;
201 } else if (FsRtlAreNamesEqual(&norootdirus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
202 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
203
204 options->no_root_dir = *val;
205 } else if (FsRtlAreNamesEqual(&nodatacowus, &us, true, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
206 DWORD* val = (DWORD*)((uint8_t*)kvfi + kvfi->DataOffset);
207
208 options->nodatacow = *val;
209 }
210 } else if (Status != STATUS_NO_MORE_ENTRIES) {
211 ERR("ZwEnumerateValueKey returned %08lx\n", Status);
212 goto end2;
213 }
214 } while (NT_SUCCESS(Status));
215
216 if (!options->compress && options->compress_force)
217 options->compress = true;
218
219 if (options->zlib_level > 9)
220 options->zlib_level = 9;
221
222 if (options->zstd_level > (uint32_t)ZSTD_maxCLevel())
223 options->zstd_level = ZSTD_maxCLevel();
224
225 if (options->flush_interval == 0)
226 options->flush_interval = mount_flush_interval;
227
229
230end2:
231 ZwClose(h);
232
233end:
234 ExFreePool(path.Buffer);
235
236 if (kvfi)
237 ExFreePool(kvfi);
238
239 return Status;
240}
241
243 UNICODE_STRING path, mountedus;
244 ULONG i, j;
247 HANDLE h;
248 DWORD data;
249
250 path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
252
253 if (!path.Buffer) {
254 ERR("out of memory\n");
256 }
257
259 i = registry_path.Length / sizeof(WCHAR);
260
261 path.Buffer[i] = '\\';
262 i++;
263
264 for (j = 0; j < 16; j++) {
265 path.Buffer[i] = hex_digit((uuid->uuid[j] & 0xF0) >> 4);
266 path.Buffer[i+1] = hex_digit(uuid->uuid[j] & 0xF);
267
268 i += 2;
269
270 if (j == 3 || j == 5 || j == 7 || j == 9) {
271 path.Buffer[i] = '-';
272 i++;
273 }
274 }
275
277
278 Status = ZwCreateKey(&h, KEY_SET_VALUE, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
279 if (!NT_SUCCESS(Status)) {
280 ERR("ZwCreateKey returned %08lx\n", Status);
281 goto end;
282 }
283
284 mountedus.Buffer = (WCHAR*)option_mounted;
285 mountedus.Length = mountedus.MaximumLength = sizeof(option_mounted) - sizeof(WCHAR);
286
287 data = 1;
288
289 Status = ZwSetValueKey(h, &mountedus, 0, REG_DWORD, &data, sizeof(DWORD));
290 if (!NT_SUCCESS(Status)) {
291 ERR("ZwSetValueKey returned %08lx\n", Status);
292 goto end2;
293 }
294
296
297end2:
298 ZwClose(h);
299
300end:
301 ExFreePool(path.Buffer);
302
303 return Status;
304}
305
307 HANDLE h;
310 ULONG index, kvbilen = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR) + (255 * sizeof(WCHAR)), retlen;
312 bool has_options = false;
313 UNICODE_STRING mountedus;
314
315 // If a volume key has any options in it, we set Mounted to 0 and return. Otherwise,
316 // we delete the whole thing.
317
318 kvbi = ExAllocatePoolWithTag(PagedPool, kvbilen, ALLOC_TAG);
319 if (!kvbi) {
320 ERR("out of memory\n");
322 }
323
325
326 Status = ZwOpenKey(&h, KEY_QUERY_VALUE | KEY_SET_VALUE | DELETE, &oa);
327 if (!NT_SUCCESS(Status)) {
328 ERR("ZwOpenKey returned %08lx\n", Status);
329 goto end;
330 }
331
332 index = 0;
333
334 mountedus.Buffer = (WCHAR*)option_mounted;
335 mountedus.Length = mountedus.MaximumLength = sizeof(option_mounted) - sizeof(WCHAR);
336
337 do {
338 Status = ZwEnumerateValueKey(h, index, KeyValueBasicInformation, kvbi, kvbilen, &retlen);
339
340 index++;
341
342 if (NT_SUCCESS(Status)) {
344
345 us.Length = us.MaximumLength = (USHORT)kvbi->NameLength;
346 us.Buffer = kvbi->Name;
347
348 if (!FsRtlAreNamesEqual(&mountedus, &us, true, NULL)) {
349 has_options = true;
350 break;
351 }
352 } else if (Status != STATUS_NO_MORE_ENTRIES) {
353 ERR("ZwEnumerateValueKey returned %08lx\n", Status);
354 goto end2;
355 }
356 } while (NT_SUCCESS(Status));
357
358 if (has_options) {
359 DWORD data = 0;
360
361 Status = ZwSetValueKey(h, &mountedus, 0, REG_DWORD, &data, sizeof(DWORD));
362 if (!NT_SUCCESS(Status)) {
363 ERR("ZwSetValueKey returned %08lx\n", Status);
364 goto end2;
365 }
366 } else {
367 Status = ZwDeleteKey(h);
368 if (!NT_SUCCESS(Status)) {
369 ERR("ZwDeleteKey returned %08lx\n", Status);
370 goto end2;
371 }
372 }
373
375
376end2:
377 ZwClose(h);
378
379end:
380 ExFreePool(kvbi);
381
382 return Status;
383}
384
388 ULONG i, j;
389
390 path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
392
393 if (!path.Buffer) {
394 ERR("out of memory\n");
396 }
397
399 i = registry_path.Length / sizeof(WCHAR);
400
401 path.Buffer[i] = '\\';
402 i++;
403
404 for (j = 0; j < 16; j++) {
405 path.Buffer[i] = hex_digit((uuid->uuid[j] & 0xF0) >> 4);
406 path.Buffer[i+1] = hex_digit(uuid->uuid[j] & 0xF);
407
408 i += 2;
409
410 if (j == 3 || j == 5 || j == 7 || j == 9) {
411 path.Buffer[i] = '-';
412 i++;
413 }
414 }
415
417 if (!NT_SUCCESS(Status)) {
418 ERR("registry_mark_volume_unmounted_path returned %08lx\n", Status);
419 goto end;
420 }
421
423
424end:
425 ExFreePool(path.Buffer);
426
427 return Status;
428}
429
430#define is_hex(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
431
433 ULONG i;
434
435 if (namelen != 36 * sizeof(WCHAR))
436 return false;
437
438 for (i = 0; i < 36; i++) {
439 if (i == 8 || i == 13 || i == 18 || i == 23) {
440 if (name[i] != '-')
441 return false;
442 } else if (!is_hex(name[i]))
443 return false;
444 }
445
446 return true;
447}
448
449typedef struct {
452} key_name;
453
454static void reset_subkeys(HANDLE h, PUNICODE_STRING reg_path) {
457 ULONG kbilen = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + (255 * sizeof(WCHAR)), retlen, index = 0;
459
461
463 if (!kbi) {
464 ERR("out of memory\n");
465 return;
466 }
467
468 do {
469 Status = ZwEnumerateKey(h, index, KeyBasicInformation, kbi, kbilen, &retlen);
470
471 index++;
472
473 if (NT_SUCCESS(Status)) {
474 key_name* kn;
475
476 TRACE("key: %.*S\n", (int)(kbi->NameLength / sizeof(WCHAR)), kbi->Name);
477
478 if (is_uuid(kbi->NameLength, kbi->Name)) {
480 if (!kn) {
481 ERR("out of memory\n");
482 goto end;
483 }
484
485 kn->name.Length = kn->name.MaximumLength = (USHORT)min(0xffff, kbi->NameLength);
487
488 if (!kn->name.Buffer) {
489 ERR("out of memory\n");
490 ExFreePool(kn);
491 goto end;
492 }
493
494 RtlCopyMemory(kn->name.Buffer, kbi->Name, kn->name.Length);
495
497 }
498 } else if (Status != STATUS_NO_MORE_ENTRIES)
499 ERR("ZwEnumerateKey returned %08lx\n", Status);
500 } while (NT_SUCCESS(Status));
501
502 le = key_names.Flink;
503 while (le != &key_names) {
506
507 path.Length = path.MaximumLength = reg_path->Length + sizeof(WCHAR) + kn->name.Length;
509
510 if (!path.Buffer) {
511 ERR("out of memory\n");
512 goto end;
513 }
514
515 RtlCopyMemory(path.Buffer, reg_path->Buffer, reg_path->Length);
516 path.Buffer[reg_path->Length / sizeof(WCHAR)] = '\\';
517 RtlCopyMemory(&path.Buffer[(reg_path->Length / sizeof(WCHAR)) + 1], kn->name.Buffer, kn->name.Length);
518
520 if (!NT_SUCCESS(Status))
521 WARN("registry_mark_volume_unmounted_path returned %08lx\n", Status);
522
523 ExFreePool(path.Buffer);
524
525 le = le->Flink;
526 }
527
528end:
529 while (!IsListEmpty(&key_names)) {
530 key_name* kn;
531
534
535 if (kn->name.Buffer)
537
538 ExFreePool(kn);
539 }
540
541 ExFreePool(kbi);
542}
543
544static void read_mappings(PUNICODE_STRING regpath) {
545 WCHAR* path;
547 HANDLE h;
551
552 static const WCHAR mappings[] = L"\\Mappings";
553
554 while (!IsListEmpty(&uid_map_list)) {
556
557 if (um->sid) ExFreePool(um->sid);
558 ExFreePool(um);
559 }
560
561 path = ExAllocatePoolWithTag(PagedPool, regpath->Length + sizeof(mappings) - sizeof(WCHAR), ALLOC_TAG);
562 if (!path) {
563 ERR("out of memory\n");
564 return;
565 }
566
567 RtlCopyMemory(path, regpath->Buffer, regpath->Length);
568 RtlCopyMemory((uint8_t*)path + regpath->Length, mappings, sizeof(mappings) - sizeof(WCHAR));
569
570 us.Buffer = path;
571 us.Length = us.MaximumLength = regpath->Length + sizeof(mappings) - sizeof(WCHAR);
572
574
575 Status = ZwCreateKey(&h, KEY_QUERY_VALUE, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, &dispos);
576
577 if (!NT_SUCCESS(Status)) {
578 ERR("ZwCreateKey returned %08lx\n", Status);
580 return;
581 }
582
585 ULONG kvfilen, retlen, i;
586
587 kvfilen = sizeof(KEY_VALUE_FULL_INFORMATION) + 256;
588 kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
589
590 if (!kvfi) {
591 ERR("out of memory\n");
593 ZwClose(h);
594 return;
595 }
596
597 i = 0;
598 do {
599 Status = ZwEnumerateValueKey(h, i, KeyValueFullInformation, kvfi, kvfilen, &retlen);
600
601 if (NT_SUCCESS(Status) && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
602 uint32_t val = 0;
603
604 RtlCopyMemory(&val, (uint8_t*)kvfi + kvfi->DataOffset, min(kvfi->DataLength, sizeof(uint32_t)));
605
606 TRACE("entry %lu = %.*S = %u\n", i, (int)(kvfi->NameLength / sizeof(WCHAR)), kvfi->Name, val);
607
608 add_user_mapping(kvfi->Name, kvfi->NameLength / sizeof(WCHAR), val);
609 }
610
611 i = i + 1;
612 } while (Status != STATUS_NO_MORE_ENTRIES);
613
614 ExFreePool(kvfi);
615 }
616
617 ZwClose(h);
618
620}
621
623 WCHAR* path;
625 HANDLE h;
629
630 static const WCHAR mappings[] = L"\\GroupMappings";
631
632 while (!IsListEmpty(&gid_map_list)) {
634
635 if (gm->sid) ExFreePool(gm->sid);
636 ExFreePool(gm);
637 }
638
639 path = ExAllocatePoolWithTag(PagedPool, regpath->Length + sizeof(mappings) - sizeof(WCHAR), ALLOC_TAG);
640 if (!path) {
641 ERR("out of memory\n");
642 return;
643 }
644
645 RtlCopyMemory(path, regpath->Buffer, regpath->Length);
646 RtlCopyMemory((uint8_t*)path + regpath->Length, mappings, sizeof(mappings) - sizeof(WCHAR));
647
648 us.Buffer = path;
649 us.Length = us.MaximumLength = regpath->Length + sizeof(mappings) - sizeof(WCHAR);
650
652
653 Status = ZwCreateKey(&h, KEY_QUERY_VALUE, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, &dispos);
654
655 if (!NT_SUCCESS(Status)) {
656 ERR("ZwCreateKey returned %08lx\n", Status);
658 return;
659 }
660
662
665 ULONG kvfilen, retlen, i;
666
667 kvfilen = sizeof(KEY_VALUE_FULL_INFORMATION) + 256;
668 kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
669
670 if (!kvfi) {
671 ERR("out of memory\n");
672 ZwClose(h);
673 return;
674 }
675
676 i = 0;
677 do {
678 Status = ZwEnumerateValueKey(h, i, KeyValueFullInformation, kvfi, kvfilen, &retlen);
679
680 if (NT_SUCCESS(Status) && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
681 uint32_t val = 0;
682
683 RtlCopyMemory(&val, (uint8_t*)kvfi + kvfi->DataOffset, min(kvfi->DataLength, sizeof(uint32_t)));
684
685 TRACE("entry %lu = %.*S = %u\n", i, (int)(kvfi->NameLength / sizeof(WCHAR)), kvfi->Name, val);
686
687 add_group_mapping(kvfi->Name, kvfi->NameLength / sizeof(WCHAR), val);
688 }
689
690 i = i + 1;
691 } while (Status != STATUS_NO_MORE_ENTRIES);
692
693 ExFreePool(kvfi);
694 } else if (dispos == REG_CREATED_NEW_KEY) {
695 static const WCHAR builtin_users[] = L"S-1-5-32-545";
696
697 UNICODE_STRING us2;
698 DWORD val;
699
700 // If we're creating the key for the first time, we add a default mapping of
701 // BUILTIN\Users to gid 100, which ought to correspond to the "users" group on Linux.
702
703 us2.Length = us2.MaximumLength = sizeof(builtin_users) - sizeof(WCHAR);
705
706 if (us2.Buffer) {
707 RtlCopyMemory(us2.Buffer, builtin_users, us2.Length);
708
709 val = 100;
710 Status = ZwSetValueKey(h, &us2, 0, REG_DWORD, &val, sizeof(DWORD));
711 if (!NT_SUCCESS(Status)) {
712 ERR("ZwSetValueKey returned %08lx\n", Status);
713 ZwClose(h);
714 return;
715 }
716
717 add_group_mapping(us2.Buffer, us2.Length / sizeof(WCHAR), val);
718
719 ExFreePool(us2.Buffer);
720 }
721 }
722
723 ZwClose(h);
724}
725
726static void get_registry_value(HANDLE h, WCHAR* string, ULONG type, void* val, ULONG size) {
727 ULONG kvfilen;
731
732 RtlInitUnicodeString(&us, string);
733
734 kvfi = NULL;
735 kvfilen = 0;
736 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
737
738 if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
739 kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
740
741 if (!kvfi) {
742 ERR("out of memory\n");
743 ZwClose(h);
744 return;
745 }
746
747 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
748
749 if (NT_SUCCESS(Status)) {
750 if (kvfi->Type == type && kvfi->DataLength >= size) {
751 RtlCopyMemory(val, ((uint8_t*)kvfi) + kvfi->DataOffset, size);
752 } else {
754 if (!NT_SUCCESS(Status)) {
755 ERR("ZwDeleteValueKey returned %08lx\n", Status);
756 }
757
758 Status = ZwSetValueKey(h, &us, 0, type, val, size);
759 if (!NT_SUCCESS(Status)) {
760 ERR("ZwSetValueKey returned %08lx\n", Status);
761 }
762 }
763 }
764
765 ExFreePool(kvfi);
766 } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
767 Status = ZwSetValueKey(h, &us, 0, type, val, size);
768
769 if (!NT_SUCCESS(Status)) {
770 ERR("ZwSetValueKey returned %08lx\n", Status);
771 }
772 } else {
773 ERR("ZwQueryValueKey returned %08lx\n", Status);
774 }
775}
776
777void read_registry(PUNICODE_STRING regpath, bool refresh) {
780 HANDLE h;
782#ifdef _DEBUG
784 ULONG kvfilen, old_debug_log_level = debug_log_level;
785 UNICODE_STRING us, old_log_file, old_log_device;
786
787 static const WCHAR def_log_file[] = L"\\??\\C:\\btrfs.log";
788#endif
789
791
792 read_mappings(regpath);
793 read_group_mappings(regpath);
794
796
798
800
801 if (!NT_SUCCESS(Status)) {
802 ERR("ZwCreateKey returned %08lx\n", Status);
803 return;
804 }
805
806 if (!refresh)
807 reset_subkeys(h, regpath);
808
824
825 if (!refresh)
826 get_registry_value(h, L"NoPNP", REG_DWORD, &no_pnp, sizeof(no_pnp));
827
828 if (mount_flush_interval == 0)
830
831#ifdef _DEBUG
832 get_registry_value(h, L"DebugLogLevel", REG_DWORD, &debug_log_level, sizeof(debug_log_level));
833
834 RtlInitUnicodeString(&us, L"LogDevice");
835
836 kvfi = NULL;
837 kvfilen = 0;
838 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
839
840 old_log_device = log_device;
841
844
845 if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
846 kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
847
848 if (!kvfi) {
849 ERR("out of memory\n");
850 ZwClose(h);
851 return;
852 }
853
854 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
855
856 if (NT_SUCCESS(Status)) {
857 if ((kvfi->Type == REG_SZ || kvfi->Type == REG_EXPAND_SZ) && kvfi->DataLength >= sizeof(WCHAR)) {
860
861 if (!log_device.Buffer) {
862 ERR("out of memory\n");
863 ExFreePool(kvfi);
864 ZwClose(h);
865 return;
866 }
867
868 RtlCopyMemory(log_device.Buffer, ((uint8_t*)kvfi) + kvfi->DataOffset, log_device.Length);
869
870 if (log_device.Buffer[(log_device.Length / sizeof(WCHAR)) - 1] == 0)
871 log_device.Length -= sizeof(WCHAR);
872 } else {
873 ERR("LogDevice was type %lu, length %lu\n", kvfi->Type, kvfi->DataLength);
874
876 if (!NT_SUCCESS(Status)) {
877 ERR("ZwDeleteValueKey returned %08lx\n", Status);
878 }
879 }
880 }
881
882 ExFreePool(kvfi);
883 } else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
884 ERR("ZwQueryValueKey returned %08lx\n", Status);
885 }
886
887 ExAcquireResourceExclusiveLite(&log_lock, true);
888
889 if (refresh && (log_device.Length != old_log_device.Length || RtlCompareMemory(log_device.Buffer, old_log_device.Buffer, log_device.Length) != log_device.Length ||
890 (!comfo && log_device.Length > 0) || (old_debug_log_level == 0 && debug_log_level > 0) || (old_debug_log_level > 0 && debug_log_level == 0))) {
891 if (comfo)
892 ObDereferenceObject(comfo);
893
894 if (log_handle) {
895 ZwClose(log_handle);
896 log_handle = NULL;
897 }
898
899 comfo = NULL;
900 comdo = NULL;
901
902 if (log_device.Length > 0 && debug_log_level > 0) {
904 if (!NT_SUCCESS(Status))
905 DbgPrint("IoGetDeviceObjectPointer returned %08lx\n", Status);
906 }
907 }
908
909 ExReleaseResourceLite(&log_lock);
910
911 if (old_log_device.Buffer)
912 ExFreePool(old_log_device.Buffer);
913
914 RtlInitUnicodeString(&us, L"LogFile");
915
916 kvfi = NULL;
917 kvfilen = 0;
918 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
919
920 old_log_file = log_file;
921
922 if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
923 kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
924
925 if (!kvfi) {
926 ERR("out of memory\n");
927 ZwClose(h);
928 return;
929 }
930
931 Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
932
933 if (NT_SUCCESS(Status)) {
934 if ((kvfi->Type == REG_SZ || kvfi->Type == REG_EXPAND_SZ) && kvfi->DataLength >= sizeof(WCHAR)) {
937
938 if (!log_file.Buffer) {
939 ERR("out of memory\n");
940 ExFreePool(kvfi);
941 ZwClose(h);
942 return;
943 }
944
945 RtlCopyMemory(log_file.Buffer, ((uint8_t*)kvfi) + kvfi->DataOffset, log_file.Length);
946
947 if (log_file.Buffer[(log_file.Length / sizeof(WCHAR)) - 1] == 0)
948 log_file.Length -= sizeof(WCHAR);
949 } else {
950 ERR("LogFile was type %lu, length %lu\n", kvfi->Type, kvfi->DataLength);
951
953 if (!NT_SUCCESS(Status))
954 ERR("ZwDeleteValueKey returned %08lx\n", Status);
955
956 log_file.Length = 0;
957 }
958 } else {
959 ERR("ZwQueryValueKey returned %08lx\n", Status);
960 log_file.Length = 0;
961 }
962
963 ExFreePool(kvfi);
964 } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
965 Status = ZwSetValueKey(h, &us, 0, REG_SZ, (void*)def_log_file, sizeof(def_log_file));
966
967 if (!NT_SUCCESS(Status))
968 ERR("ZwSetValueKey returned %08lx\n", Status);
969
970 log_file.Length = 0;
971 } else {
972 ERR("ZwQueryValueKey returned %08lx\n", Status);
973 log_file.Length = 0;
974 }
975
976 if (log_file.Length == 0) {
977 log_file.Length = log_file.MaximumLength = sizeof(def_log_file) - sizeof(WCHAR);
979
980 if (!log_file.Buffer) {
981 ERR("out of memory\n");
982 ZwClose(h);
983 return;
984 }
985
987 }
988
989 ExAcquireResourceExclusiveLite(&log_lock, true);
990
991 if (refresh && (log_file.Length != old_log_file.Length || RtlCompareMemory(log_file.Buffer, old_log_file.Buffer, log_file.Length) != log_file.Length ||
992 (!log_handle && log_file.Length > 0) || (old_debug_log_level == 0 && debug_log_level > 0) || (old_debug_log_level > 0 && debug_log_level == 0))) {
993 if (log_handle) {
994 ZwClose(log_handle);
995 log_handle = NULL;
996 }
997
998 if (!comfo && log_file.Length > 0 && refresh && debug_log_level > 0) {
1000
1002
1003 Status = ZwCreateFile(&log_handle, FILE_WRITE_DATA, &oa, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
1005 if (!NT_SUCCESS(Status)) {
1006 DbgPrint("ZwCreateFile returned %08lx\n", Status);
1007 log_handle = NULL;
1008 }
1009 }
1010 }
1011
1012 ExReleaseResourceLite(&log_lock);
1013
1014 if (old_log_file.Buffer)
1015 ExFreePool(old_log_file.Buffer);
1016#endif
1017
1018 ZwClose(h);
1019}
1020
1021_Function_class_(WORKER_THREAD_ROUTINE)
1022static void __stdcall registry_work_item(PVOID Parameter) {
1024 HANDLE regh = (HANDLE)Parameter;
1026
1027 TRACE("registry changed\n");
1028
1030
1031 Status = ZwNotifyChangeKey(regh, NULL, (PVOID)&wqi, (PVOID)DelayedWorkQueue, &iosb, REG_NOTIFY_CHANGE_LAST_SET, true, NULL, 0, true);
1032 if (!NT_SUCCESS(Status))
1033 ERR("ZwNotifyChangeKey returned %08lx\n", Status);
1034}
1035
1039
1040 ExInitializeWorkItem(&wqi, registry_work_item, regh);
1041
1042 Status = ZwNotifyChangeKey(regh, NULL, (PVOID)&wqi, (PVOID)DelayedWorkQueue, &iosb, REG_NOTIFY_CHANGE_LAST_SET, true, NULL, 0, true);
1043 if (!NT_SUCCESS(Status))
1044 ERR("ZwNotifyChangeKey returned %08lx\n", Status);
1045}
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define index(s, c)
Definition: various.h:29
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
void add_user_mapping(WCHAR *sidstring, ULONG sidstringlength, uint32_t uid)
Definition: security.c:56
void add_group_mapping(WCHAR *sidstring, ULONG sidstringlength, uint32_t gid)
Definition: security.c:145
#define ALLOC_TAG
Definition: btrfs_drv.h:87
#define hex_digit(c)
Definition: btrfs_drv.h:1748
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
uint32_t mount_readonly
Definition: btrfs.c:84
uint32_t mount_max_inline
Definition: btrfs.c:78
uint32_t mount_no_trim
Definition: btrfs.c:81
uint32_t mount_compress
Definition: btrfs.c:72
uint32_t mount_allow_degraded
Definition: btrfs.c:83
uint32_t mount_skip_balance
Definition: btrfs.c:79
uint32_t mount_zlib_level
Definition: btrfs.c:75
uint32_t mount_zstd_level
Definition: btrfs.c:76
uint32_t mount_nodatacow
Definition: btrfs.c:86
uint32_t mount_compress_type
Definition: btrfs.c:74
uint32_t mount_no_root_dir
Definition: btrfs.c:85
uint32_t mount_flush_interval
Definition: btrfs.c:77
uint32_t no_pnp
Definition: btrfs.c:87
uint32_t mount_no_barrier
Definition: btrfs.c:80
uint32_t mount_compress_force
Definition: btrfs.c:73
uint32_t mount_clear_cache
Definition: btrfs.c:82
uint32_t debug_log_level
Definition: btrfs.c:71
#define BTRFS_COMPRESSION_ZSTD
Definition: btrfs.h:68
UNICODE_STRING log_file
Definition: registry.c:21
NTSTATUS registry_load_volume_options(device_extension *Vcb)
Definition: registry.c:36
static void get_registry_value(HANDLE h, WCHAR *string, ULONG type, void *val, ULONG size)
Definition: registry.c:726
static void read_mappings(PUNICODE_STRING regpath)
Definition: registry.c:544
UNICODE_STRING log_device
Definition: btrfs.c:89
NTSTATUS registry_mark_volume_unmounted(BTRFS_UUID *uuid)
Definition: registry.c:385
UNICODE_STRING registry_path
Definition: registry.c:21
static NTSTATUS registry_mark_volume_unmounted_path(PUNICODE_STRING path)
Definition: registry.c:306
static bool is_uuid(ULONG namelen, WCHAR *name)
Definition: registry.c:432
static void reset_subkeys(HANDLE h, PUNICODE_STRING reg_path)
Definition: registry.c:454
WORK_QUEUE_ITEM wqi
Definition: registry.c:32
ERESOURCE mapping_lock
Definition: btrfs.c:103
void watch_registry(HANDLE regh)
Definition: registry.c:1036
LIST_ENTRY uid_map_list
Definition: btrfs.c:68
void read_registry(PUNICODE_STRING regpath, bool refresh)
Definition: registry.c:777
LIST_ENTRY gid_map_list
Definition: registry.c:22
NTSTATUS registry_mark_volume_mounted(BTRFS_UUID *uuid)
Definition: registry.c:242
static const WCHAR option_mounted[]
Definition: registry.c:34
#define is_hex(c)
Definition: registry.c:430
static void read_group_mappings(PUNICODE_STRING regpath)
Definition: registry.c:622
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
unsigned long DWORD
Definition: ntddk_ex.h:95
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
NTSYSAPI NTSTATUS NTAPI ZwDeleteValueKey(__in IN HANDLE Key, __in IN PUNICODE_STRING ValueName)
Status
Definition: gdiplustypes.h:25
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLint namelen
Definition: glext.h:7232
GLuint index
Definition: glext.h:6031
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define DbgPrint
Definition: hal.h:12
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
Definition: msctf.idl:550
ROSDATA VSC_LPWSTR key_names[]
Definition: kbda1.c:260
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
static const BYTE us[]
Definition: encode.c:689
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG const UNICODE_STRING ULONG PULONG dispos
Definition: reg.c:132
#define min(a, b)
Definition: monoChain.cc:55
#define _Function_class_(x)
Definition: ms_sal.h:2946
BYTE uint8_t
Definition: msvideo1.c:66
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define uint8_t
Definition: nsiface.idl:59
struct _KEY_VALUE_BASIC_INFORMATION KEY_VALUE_BASIC_INFORMATION
struct _KEY_VALUE_FULL_INFORMATION KEY_VALUE_FULL_INFORMATION
@ KeyBasicInformation
Definition: nt_native.h:1131
#define FILE_WRITE_DATA
Definition: nt_native.h:631
@ KeyValueBasicInformation
Definition: nt_native.h:1180
@ KeyValueFullInformation
Definition: nt_native.h:1181
struct _KEY_BASIC_INFORMATION KEY_BASIC_INFORMATION
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define DELETE
Definition: nt_native.h:57
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define KEY_SET_VALUE
Definition: nt_native.h:1017
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
BOOLEAN NTAPI FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1, IN PCUNICODE_STRING Name2, IN BOOLEAN IgnoreCase, IN PCWCH UpcaseTable OPTIONAL)
Definition: name.c:296
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
#define REG_QWORD
Definition: sdbapi.c:597
#define REG_DWORD
Definition: sdbapi.c:596
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define TRACE(s)
Definition: solgame.cpp:4
#define true
Definition: stdbool.h:36
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT MaximumLength
Definition: env_spec_w32.h:370
PSID sid
Definition: btrfs_drv.h:910
LIST_ENTRY list_entry
Definition: registry.c:451
UNICODE_STRING name
Definition: registry.c:450
Definition: list.h:27
Definition: name.c:39
PSID sid
Definition: btrfs_drv.h:904
PVOID HANDLE
Definition: typedefs.h:73
#define __stdcall
Definition: typedefs.h:25
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define REG_NOTIFY_CHANGE_LAST_SET
Definition: winreg.h:40
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ DelayedWorkQueue
Definition: extypes.h:190
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323
__wchar_t WCHAR
Definition: xmlstorage.h:180
ZSTDLIB_API int ZSTD_maxCLevel(void)