ReactOS  0.4.13-dev-247-g0f29b3f
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 
23 extern ERESOURCE mapping_lock;
24 
25 #ifdef _DEBUG
26 extern HANDLE log_handle;
27 extern ERESOURCE log_lock;
28 extern PFILE_OBJECT comfo;
29 extern PDEVICE_OBJECT comdo;
30 #endif
31 
33 
34 static 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;
43  ULONG i, j, kvfilen, index, retlen;
45  HANDLE h;
46 
47  options->compress = mount_compress;
48  options->compress_force = mount_compress_force;
50  options->readonly = mount_readonly;
51  options->zlib_level = mount_zlib_level;
52  options->zstd_level = mount_zstd_level;
53  options->flush_interval = mount_flush_interval;
54  options->max_inline = min(mount_max_inline, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - sizeof(EXTENT_DATA) + 1);
55  options->skip_balance = mount_skip_balance;
56  options->no_barrier = mount_no_barrier;
57  options->no_trim = mount_no_trim;
58  options->clear_cache = mount_clear_cache;
59  options->allow_degraded = mount_allow_degraded;
60  options->subvol_id = 0;
61 
62  path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
64 
65  if (!path.Buffer) {
66  ERR("out of memory\n");
68  }
69 
71  i = registry_path.Length / sizeof(WCHAR);
72 
73  path.Buffer[i] = '\\';
74  i++;
75 
76  for (j = 0; j < 16; j++) {
77  path.Buffer[i] = hex_digit((uuid->uuid[j] & 0xF0) >> 4);
78  path.Buffer[i+1] = hex_digit(uuid->uuid[j] & 0xF);
79 
80  i += 2;
81 
82  if (j == 3 || j == 5 || j == 7 || j == 9) {
83  path.Buffer[i] = '-';
84  i++;
85  }
86  }
87 
88  kvfilen = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR) + (255 * sizeof(WCHAR));
89  kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
90  if (!kvfi) {
91  ERR("out of memory\n");
93  goto end;
94  }
95 
97 
98  Status = ZwOpenKey(&h, KEY_QUERY_VALUE, &oa);
101  goto end;
102  } else if (!NT_SUCCESS(Status)) {
103  ERR("ZwOpenKey returned %08x\n", Status);
104  goto end;
105  }
106 
107  index = 0;
108 
109  RtlInitUnicodeString(&ignoreus, L"Ignore");
110  RtlInitUnicodeString(&compressus, L"Compress");
111  RtlInitUnicodeString(&compressforceus, L"CompressForce");
112  RtlInitUnicodeString(&compresstypeus, L"CompressType");
113  RtlInitUnicodeString(&readonlyus, L"Readonly");
114  RtlInitUnicodeString(&zliblevelus, L"ZlibLevel");
115  RtlInitUnicodeString(&flushintervalus, L"FlushInterval");
116  RtlInitUnicodeString(&maxinlineus, L"MaxInline");
117  RtlInitUnicodeString(&subvolidus, L"SubvolId");
118  RtlInitUnicodeString(&skipbalanceus, L"SkipBalance");
119  RtlInitUnicodeString(&nobarrierus, L"NoBarrier");
120  RtlInitUnicodeString(&notrimus, L"NoTrim");
121  RtlInitUnicodeString(&clearcacheus, L"ClearCache");
122  RtlInitUnicodeString(&allowdegradedus, L"AllowDegraded");
123  RtlInitUnicodeString(&zstdlevelus, L"ZstdLevel");
124 
125  do {
126  Status = ZwEnumerateValueKey(h, index, KeyValueFullInformation, kvfi, kvfilen, &retlen);
127 
128  index++;
129 
130  if (NT_SUCCESS(Status)) {
132 
133  us.Length = us.MaximumLength = (USHORT)kvfi->NameLength;
134  us.Buffer = kvfi->Name;
135 
136  if (FsRtlAreNamesEqual(&ignoreus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
137  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
138 
139  options->ignore = *val != 0 ? TRUE : FALSE;
140  } else if (FsRtlAreNamesEqual(&compressus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
141  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
142 
143  options->compress = *val != 0 ? TRUE : FALSE;
144  } else if (FsRtlAreNamesEqual(&compressforceus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
145  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
146 
147  options->compress_force = *val != 0 ? TRUE : FALSE;
148  } else if (FsRtlAreNamesEqual(&compresstypeus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
149  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
150 
151  options->compress_type = (UINT8)(*val > BTRFS_COMPRESSION_ZSTD ? 0 : *val);
152  } else if (FsRtlAreNamesEqual(&readonlyus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
153  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
154 
155  options->readonly = *val != 0 ? TRUE : FALSE;
156  } else if (FsRtlAreNamesEqual(&zliblevelus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
157  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
158 
159  options->zlib_level = *val;
160  } else if (FsRtlAreNamesEqual(&flushintervalus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
161  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
162 
163  options->flush_interval = *val;
164  } else if (FsRtlAreNamesEqual(&maxinlineus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
165  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
166 
167  options->max_inline = min(*val, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - sizeof(EXTENT_DATA) + 1);
168  } else if (FsRtlAreNamesEqual(&subvolidus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_QWORD) {
169  UINT64* val = (UINT64*)((UINT8*)kvfi + kvfi->DataOffset);
170 
171  options->subvol_id = *val;
172  } else if (FsRtlAreNamesEqual(&skipbalanceus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
173  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
174 
175  options->skip_balance = *val;
176  } else if (FsRtlAreNamesEqual(&nobarrierus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
177  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
178 
179  options->no_barrier = *val;
180  } else if (FsRtlAreNamesEqual(&notrimus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
181  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
182 
183  options->no_trim = *val;
184  } else if (FsRtlAreNamesEqual(&clearcacheus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
185  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
186 
187  options->clear_cache = *val;
188  } else if (FsRtlAreNamesEqual(&allowdegradedus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
189  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
190 
191  options->allow_degraded = *val;
192  } else if (FsRtlAreNamesEqual(&zstdlevelus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
193  DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
194 
195  options->zstd_level = *val;
196  }
197  } else if (Status != STATUS_NO_MORE_ENTRIES) {
198  ERR("ZwEnumerateValueKey returned %08x\n", Status);
199  goto end2;
200  }
201  } while (NT_SUCCESS(Status));
202 
203  if (!options->compress && options->compress_force)
204  options->compress = TRUE;
205 
206  if (options->zlib_level > 9)
207  options->zlib_level = 9;
208 
209  if (options->zstd_level > (UINT32)ZSTD_maxCLevel())
210  options->zstd_level = ZSTD_maxCLevel();
211 
212  if (options->flush_interval == 0)
213  options->flush_interval = mount_flush_interval;
214 
216 
217 end2:
218  ZwClose(h);
219 
220 end:
221  ExFreePool(path.Buffer);
222 
223  if (kvfi)
224  ExFreePool(kvfi);
225 
226  return Status;
227 }
228 
230  UNICODE_STRING path, mountedus;
231  ULONG i, j;
234  HANDLE h;
235  DWORD data;
236 
237  path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
239 
240  if (!path.Buffer) {
241  ERR("out of memory\n");
243  }
244 
246  i = registry_path.Length / sizeof(WCHAR);
247 
248  path.Buffer[i] = '\\';
249  i++;
250 
251  for (j = 0; j < 16; j++) {
252  path.Buffer[i] = hex_digit((uuid->uuid[j] & 0xF0) >> 4);
253  path.Buffer[i+1] = hex_digit(uuid->uuid[j] & 0xF);
254 
255  i += 2;
256 
257  if (j == 3 || j == 5 || j == 7 || j == 9) {
258  path.Buffer[i] = '-';
259  i++;
260  }
261  }
262 
264 
265  Status = ZwCreateKey(&h, KEY_SET_VALUE, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
266  if (!NT_SUCCESS(Status)) {
267  ERR("ZwCreateKey returned %08x\n", Status);
268  goto end;
269  }
270 
271  mountedus.Buffer = (WCHAR*)option_mounted;
272  mountedus.Length = mountedus.MaximumLength = sizeof(option_mounted) - sizeof(WCHAR);
273 
274  data = 1;
275 
276  Status = ZwSetValueKey(h, &mountedus, 0, REG_DWORD, &data, sizeof(DWORD));
277  if (!NT_SUCCESS(Status)) {
278  ERR("ZwSetValueKey returned %08x\n", Status);
279  goto end2;
280  }
281 
283 
284 end2:
285  ZwClose(h);
286 
287 end:
288  ExFreePool(path.Buffer);
289 
290  return Status;
291 }
292 
294  HANDLE h;
297  ULONG index, kvbilen = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR) + (255 * sizeof(WCHAR)), retlen;
299  BOOL has_options = FALSE;
300  UNICODE_STRING mountedus;
301 
302  // If a volume key has any options in it, we set Mounted to 0 and return. Otherwise,
303  // we delete the whole thing.
304 
305  kvbi = ExAllocatePoolWithTag(PagedPool, kvbilen, ALLOC_TAG);
306  if (!kvbi) {
307  ERR("out of memory\n");
309  }
310 
312 
313  Status = ZwOpenKey(&h, KEY_QUERY_VALUE | KEY_SET_VALUE | DELETE, &oa);
314  if (!NT_SUCCESS(Status)) {
315  ERR("ZwOpenKey returned %08x\n", Status);
316  goto end;
317  }
318 
319  index = 0;
320 
321  mountedus.Buffer = (WCHAR*)option_mounted;
322  mountedus.Length = mountedus.MaximumLength = sizeof(option_mounted) - sizeof(WCHAR);
323 
324  do {
325  Status = ZwEnumerateValueKey(h, index, KeyValueBasicInformation, kvbi, kvbilen, &retlen);
326 
327  index++;
328 
329  if (NT_SUCCESS(Status)) {
331 
332  us.Length = us.MaximumLength = (USHORT)kvbi->NameLength;
333  us.Buffer = kvbi->Name;
334 
335  if (!FsRtlAreNamesEqual(&mountedus, &us, TRUE, NULL)) {
336  has_options = TRUE;
337  break;
338  }
339  } else if (Status != STATUS_NO_MORE_ENTRIES) {
340  ERR("ZwEnumerateValueKey returned %08x\n", Status);
341  goto end2;
342  }
343  } while (NT_SUCCESS(Status));
344 
345  if (has_options) {
346  DWORD data = 0;
347 
348  Status = ZwSetValueKey(h, &mountedus, 0, REG_DWORD, &data, sizeof(DWORD));
349  if (!NT_SUCCESS(Status)) {
350  ERR("ZwSetValueKey returned %08x\n", Status);
351  goto end2;
352  }
353  } else {
354  Status = ZwDeleteKey(h);
355  if (!NT_SUCCESS(Status)) {
356  ERR("ZwDeleteKey returned %08x\n", Status);
357  goto end2;
358  }
359  }
360 
362 
363 end2:
364  ZwClose(h);
365 
366 end:
367  ExFreePool(kvbi);
368 
369  return Status;
370 }
371 
375  ULONG i, j;
376 
377  path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
379 
380  if (!path.Buffer) {
381  ERR("out of memory\n");
383  }
384 
386  i = registry_path.Length / sizeof(WCHAR);
387 
388  path.Buffer[i] = '\\';
389  i++;
390 
391  for (j = 0; j < 16; j++) {
392  path.Buffer[i] = hex_digit((uuid->uuid[j] & 0xF0) >> 4);
393  path.Buffer[i+1] = hex_digit(uuid->uuid[j] & 0xF);
394 
395  i += 2;
396 
397  if (j == 3 || j == 5 || j == 7 || j == 9) {
398  path.Buffer[i] = '-';
399  i++;
400  }
401  }
402 
404  if (!NT_SUCCESS(Status)) {
405  ERR("registry_mark_volume_unmounted_path returned %08x\n", Status);
406  goto end;
407  }
408 
410 
411 end:
412  ExFreePool(path.Buffer);
413 
414  return Status;
415 }
416 
417 #define is_hex(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
418 
420  ULONG i;
421 
422  if (namelen != 36 * sizeof(WCHAR))
423  return FALSE;
424 
425  for (i = 0; i < 36; i++) {
426  if (i == 8 || i == 13 || i == 18 || i == 23) {
427  if (name[i] != '-')
428  return FALSE;
429  } else if (!is_hex(name[i]))
430  return FALSE;
431  }
432 
433  return TRUE;
434 }
435 
436 typedef struct {
439 } key_name;
440 
441 static void reset_subkeys(HANDLE h, PUNICODE_STRING reg_path) {
444  ULONG kbilen = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + (255 * sizeof(WCHAR)), retlen, index = 0;
445  LIST_ENTRY key_names, *le;
446 
448 
449  kbi = ExAllocatePoolWithTag(PagedPool, kbilen, ALLOC_TAG);
450  if (!kbi) {
451  ERR("out of memory\n");
452  return;
453  }
454 
455  do {
456  Status = ZwEnumerateKey(h, index, KeyBasicInformation, kbi, kbilen, &retlen);
457 
458  index++;
459 
460  if (NT_SUCCESS(Status)) {
461  key_name* kn;
462 
463  TRACE("key: %.*S\n", kbi->NameLength / sizeof(WCHAR), kbi->Name);
464 
465  if (is_uuid(kbi->NameLength, kbi->Name)) {
467  if (!kn) {
468  ERR("out of memory\n");
469  goto end;
470  }
471 
472  kn->name.Length = kn->name.MaximumLength = (USHORT)min(0xffff, kbi->NameLength);
474 
475  if (!kn->name.Buffer) {
476  ERR("out of memory\n");
477  ExFreePool(kn);
478  goto end;
479  }
480 
481  RtlCopyMemory(kn->name.Buffer, kbi->Name, kn->name.Length);
482 
484  }
485  } else if (Status != STATUS_NO_MORE_ENTRIES)
486  ERR("ZwEnumerateKey returned %08x\n", Status);
487  } while (NT_SUCCESS(Status));
488 
489  le = key_names.Flink;
490  while (le != &key_names) {
493 
494  path.Length = path.MaximumLength = reg_path->Length + sizeof(WCHAR) + kn->name.Length;
496 
497  if (!path.Buffer) {
498  ERR("out of memory\n");
499  goto end;
500  }
501 
502  RtlCopyMemory(path.Buffer, reg_path->Buffer, reg_path->Length);
503  path.Buffer[reg_path->Length / sizeof(WCHAR)] = '\\';
504  RtlCopyMemory(&path.Buffer[(reg_path->Length / sizeof(WCHAR)) + 1], kn->name.Buffer, kn->name.Length);
505 
507  if (!NT_SUCCESS(Status))
508  WARN("registry_mark_volume_unmounted_path returned %08x\n", Status);
509 
510  ExFreePool(path.Buffer);
511 
512  le = le->Flink;
513  }
514 
515 end:
516  while (!IsListEmpty(&key_names)) {
517  key_name* kn;
518 
519  le = RemoveHeadList(&key_names);
521 
522  if (kn->name.Buffer)
523  ExFreePool(kn->name.Buffer);
524 
525  ExFreePool(kn);
526  }
527 
528  ExFreePool(kbi);
529 }
530 
531 static void read_mappings(PUNICODE_STRING regpath) {
532  WCHAR* path;
534  HANDLE h;
536  ULONG dispos;
538 
539  static const WCHAR mappings[] = L"\\Mappings";
540 
541  while (!IsListEmpty(&uid_map_list)) {
543 
544  if (um->sid) ExFreePool(um->sid);
545  ExFreePool(um);
546  }
547 
548  path = ExAllocatePoolWithTag(PagedPool, regpath->Length + sizeof(mappings) - sizeof(WCHAR), ALLOC_TAG);
549  if (!path) {
550  ERR("out of memory\n");
551  return;
552  }
553 
554  RtlCopyMemory(path, regpath->Buffer, regpath->Length);
555  RtlCopyMemory((UINT8*)path + regpath->Length, mappings, sizeof(mappings) - sizeof(WCHAR));
556 
557  us.Buffer = path;
558  us.Length = us.MaximumLength = regpath->Length + sizeof(mappings) - sizeof(WCHAR);
559 
561 
562  Status = ZwCreateKey(&h, KEY_QUERY_VALUE, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, &dispos);
563 
564  if (!NT_SUCCESS(Status)) {
565  ERR("ZwCreateKey returned %08x\n", Status);
566  ExFreePool(path);
567  return;
568  }
569 
572  ULONG kvfilen, retlen, i;
573 
574  kvfilen = sizeof(KEY_VALUE_FULL_INFORMATION) + 256;
575  kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
576 
577  if (!kvfi) {
578  ERR("out of memory\n");
579  ExFreePool(path);
580  ZwClose(h);
581  return;
582  }
583 
584  i = 0;
585  do {
586  Status = ZwEnumerateValueKey(h, i, KeyValueFullInformation, kvfi, kvfilen, &retlen);
587 
588  if (NT_SUCCESS(Status) && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
589  UINT32 val = 0;
590 
591  RtlCopyMemory(&val, (UINT8*)kvfi + kvfi->DataOffset, min(kvfi->DataLength, sizeof(UINT32)));
592 
593  TRACE("entry %u = %.*S = %u\n", i, kvfi->NameLength / sizeof(WCHAR), kvfi->Name, val);
594 
595  add_user_mapping(kvfi->Name, kvfi->NameLength / sizeof(WCHAR), val);
596  }
597 
598  i = i + 1;
599  } while (Status != STATUS_NO_MORE_ENTRIES);
600 
601  ExFreePool(kvfi);
602  }
603 
604  ZwClose(h);
605 
606  ExFreePool(path);
607 }
608 
609 static void read_group_mappings(PUNICODE_STRING regpath) {
610  WCHAR* path;
612  HANDLE h;
614  ULONG dispos;
616 
617  static const WCHAR mappings[] = L"\\GroupMappings";
618 
619  while (!IsListEmpty(&gid_map_list)) {
621 
622  if (gm->sid) ExFreePool(gm->sid);
623  ExFreePool(gm);
624  }
625 
626  path = ExAllocatePoolWithTag(PagedPool, regpath->Length + sizeof(mappings) - sizeof(WCHAR), ALLOC_TAG);
627  if (!path) {
628  ERR("out of memory\n");
629  return;
630  }
631 
632  RtlCopyMemory(path, regpath->Buffer, regpath->Length);
633  RtlCopyMemory((UINT8*)path + regpath->Length, mappings, sizeof(mappings) - sizeof(WCHAR));
634 
635  us.Buffer = path;
636  us.Length = us.MaximumLength = regpath->Length + sizeof(mappings) - sizeof(WCHAR);
637 
639 
640  Status = ZwCreateKey(&h, KEY_QUERY_VALUE, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, &dispos);
641 
642  if (!NT_SUCCESS(Status)) {
643  ERR("ZwCreateKey returned %08x\n", Status);
644  ExFreePool(path);
645  return;
646  }
647 
648  ExFreePool(path);
649 
652  ULONG kvfilen, retlen, i;
653 
654  kvfilen = sizeof(KEY_VALUE_FULL_INFORMATION) + 256;
655  kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
656 
657  if (!kvfi) {
658  ERR("out of memory\n");
659  ZwClose(h);
660  return;
661  }
662 
663  i = 0;
664  do {
665  Status = ZwEnumerateValueKey(h, i, KeyValueFullInformation, kvfi, kvfilen, &retlen);
666 
667  if (NT_SUCCESS(Status) && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
668  UINT32 val = 0;
669 
670  RtlCopyMemory(&val, (UINT8*)kvfi + kvfi->DataOffset, min(kvfi->DataLength, sizeof(UINT32)));
671 
672  TRACE("entry %u = %.*S = %u\n", i, kvfi->NameLength / sizeof(WCHAR), kvfi->Name, val);
673 
674  add_group_mapping(kvfi->Name, kvfi->NameLength / sizeof(WCHAR), val);
675  }
676 
677  i = i + 1;
678  } while (Status != STATUS_NO_MORE_ENTRIES);
679 
680  ExFreePool(kvfi);
681  } else if (dispos == REG_CREATED_NEW_KEY) {
682  WCHAR* builtin_users = L"S-1-5-32-545";
683  UNICODE_STRING us2;
684  DWORD val;
685 
686  // If we're creating the key for the first time, we add a default mapping of
687  // BUILTIN\Users to gid 100, which ought to correspond to the "users" group on Linux.
688 
689  us2.Length = us2.MaximumLength = sizeof(builtin_users) - sizeof(WCHAR);
691 
692  if (us2.Buffer) {
693  RtlCopyMemory(us2.Buffer, builtin_users, us2.Length);
694 
695  val = 100;
696  Status = ZwSetValueKey(h, &us2, 0, REG_DWORD, &val, sizeof(DWORD));
697  if (!NT_SUCCESS(Status)) {
698  ERR("ZwSetValueKey returned %08x\n", Status);
699  ZwClose(h);
700  return;
701  }
702 
703  add_group_mapping(us2.Buffer, us2.Length / sizeof(WCHAR), val);
704 
705  ExFreePool(us2.Buffer);
706  }
707  }
708 
709  ZwClose(h);
710 }
711 
712 static void get_registry_value(HANDLE h, WCHAR* string, ULONG type, void* val, ULONG size) {
713  ULONG kvfilen;
717 
718  RtlInitUnicodeString(&us, string);
719 
720  kvfi = NULL;
721  kvfilen = 0;
722  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
723 
724  if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
725  kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
726 
727  if (!kvfi) {
728  ERR("out of memory\n");
729  ZwClose(h);
730  return;
731  }
732 
733  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
734 
735  if (NT_SUCCESS(Status)) {
736  if (kvfi->Type == type && kvfi->DataLength >= size) {
737  RtlCopyMemory(val, ((UINT8*)kvfi) + kvfi->DataOffset, size);
738  } else {
739  Status = ZwDeleteValueKey(h, &us);
740  if (!NT_SUCCESS(Status)) {
741  ERR("ZwDeleteValueKey returned %08x\n", Status);
742  }
743 
744  Status = ZwSetValueKey(h, &us, 0, type, val, size);
745  if (!NT_SUCCESS(Status)) {
746  ERR("ZwSetValueKey returned %08x\n", Status);
747  }
748  }
749  }
750 
751  ExFreePool(kvfi);
752  } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
753  Status = ZwSetValueKey(h, &us, 0, type, val, size);
754 
755  if (!NT_SUCCESS(Status)) {
756  ERR("ZwSetValueKey returned %08x\n", Status);
757  }
758  } else {
759  ERR("ZwQueryValueKey returned %08x\n", Status);
760  }
761 }
762 
763 void read_registry(PUNICODE_STRING regpath, BOOL refresh) {
766  HANDLE h;
767  ULONG dispos;
768 #ifdef _DEBUG
770  ULONG kvfilen, old_debug_log_level = debug_log_level;
771  UNICODE_STRING us, old_log_file, old_log_device;
772 
773  static const WCHAR def_log_file[] = L"\\??\\C:\\btrfs.log";
774 #endif
775 
777 
778  read_mappings(regpath);
779  read_group_mappings(regpath);
780 
782 
784 
786 
787  if (!NT_SUCCESS(Status)) {
788  ERR("ZwCreateKey returned %08x\n", Status);
789  return;
790  }
791 
792  if (!refresh)
793  reset_subkeys(h, regpath);
794 
808 
809  if (!refresh)
810  get_registry_value(h, L"NoPNP", REG_DWORD, &no_pnp, sizeof(no_pnp));
811 
812  if (mount_flush_interval == 0)
814 
815 #ifdef _DEBUG
816  get_registry_value(h, L"DebugLogLevel", REG_DWORD, &debug_log_level, sizeof(debug_log_level));
817 
818  RtlInitUnicodeString(&us, L"LogDevice");
819 
820  kvfi = NULL;
821  kvfilen = 0;
822  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
823 
824  old_log_device = log_device;
825 
828 
829  if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
830  kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
831 
832  if (!kvfi) {
833  ERR("out of memory\n");
834  ZwClose(h);
835  return;
836  }
837 
838  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
839 
840  if (NT_SUCCESS(Status)) {
841  if ((kvfi->Type == REG_SZ || kvfi->Type == REG_EXPAND_SZ) && kvfi->DataLength >= sizeof(WCHAR)) {
844 
845  if (!log_device.Buffer) {
846  ERR("out of memory\n");
847  ExFreePool(kvfi);
848  ZwClose(h);
849  return;
850  }
851 
852  RtlCopyMemory(log_device.Buffer, ((UINT8*)kvfi) + kvfi->DataOffset, log_device.Length);
853 
854  if (log_device.Buffer[(log_device.Length / sizeof(WCHAR)) - 1] == 0)
855  log_device.Length -= sizeof(WCHAR);
856  } else {
857  ERR("LogDevice was type %u, length %u\n", kvfi->Type, kvfi->DataLength);
858 
859  Status = ZwDeleteValueKey(h, &us);
860  if (!NT_SUCCESS(Status)) {
861  ERR("ZwDeleteValueKey returned %08x\n", Status);
862  }
863  }
864  }
865 
866  ExFreePool(kvfi);
867  } else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
868  ERR("ZwQueryValueKey returned %08x\n", Status);
869  }
870 
872 
873  if (refresh && (log_device.Length != old_log_device.Length || RtlCompareMemory(log_device.Buffer, old_log_device.Buffer, log_device.Length) != log_device.Length ||
874  (!comfo && log_device.Length > 0) || (old_debug_log_level == 0 && debug_log_level > 0) || (old_debug_log_level > 0 && debug_log_level == 0))) {
875  if (comfo)
876  ObDereferenceObject(comfo);
877 
878  if (log_handle) {
879  ZwClose(log_handle);
880  log_handle = NULL;
881  }
882 
883  comfo = NULL;
884  comdo = NULL;
885 
886  if (log_device.Length > 0 && debug_log_level > 0) {
888  if (!NT_SUCCESS(Status))
889  DbgPrint("IoGetDeviceObjectPointer returned %08x\n", Status);
890  }
891  }
892 
893  ExReleaseResourceLite(&log_lock);
894 
895  if (old_log_device.Buffer)
896  ExFreePool(old_log_device.Buffer);
897 
898  RtlInitUnicodeString(&us, L"LogFile");
899 
900  kvfi = NULL;
901  kvfilen = 0;
902  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
903 
904  old_log_file = log_file;
905 
906  if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
907  kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
908 
909  if (!kvfi) {
910  ERR("out of memory\n");
911  ZwClose(h);
912  return;
913  }
914 
915  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
916 
917  if (NT_SUCCESS(Status)) {
918  if ((kvfi->Type == REG_SZ || kvfi->Type == REG_EXPAND_SZ) && kvfi->DataLength >= sizeof(WCHAR)) {
921 
922  if (!log_file.Buffer) {
923  ERR("out of memory\n");
924  ExFreePool(kvfi);
925  ZwClose(h);
926  return;
927  }
928 
929  RtlCopyMemory(log_file.Buffer, ((UINT8*)kvfi) + kvfi->DataOffset, log_file.Length);
930 
931  if (log_file.Buffer[(log_file.Length / sizeof(WCHAR)) - 1] == 0)
932  log_file.Length -= sizeof(WCHAR);
933  } else {
934  ERR("LogFile was type %u, length %u\n", kvfi->Type, kvfi->DataLength);
935 
936  Status = ZwDeleteValueKey(h, &us);
937  if (!NT_SUCCESS(Status))
938  ERR("ZwDeleteValueKey returned %08x\n", Status);
939 
940  log_file.Length = 0;
941  }
942  } else {
943  ERR("ZwQueryValueKey returned %08\n", Status);
944  log_file.Length = 0;
945  }
946 
947  ExFreePool(kvfi);
948  } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
949  Status = ZwSetValueKey(h, &us, 0, REG_SZ, (void*)def_log_file, sizeof(def_log_file));
950 
951  if (!NT_SUCCESS(Status))
952  ERR("ZwSetValueKey returned %08x\n", Status);
953 
954  log_file.Length = 0;
955  } else {
956  ERR("ZwQueryValueKey returned %08x\n", Status);
957  log_file.Length = 0;
958  }
959 
960  if (log_file.Length == 0) {
961  log_file.Length = log_file.MaximumLength = sizeof(def_log_file) - sizeof(WCHAR);
963 
964  if (!log_file.Buffer) {
965  ERR("out of memory\n");
966  ZwClose(h);
967  return;
968  }
969 
970  RtlCopyMemory(log_file.Buffer, def_log_file, log_file.Length);
971  }
972 
974 
975  if (refresh && (log_file.Length != old_log_file.Length || RtlCompareMemory(log_file.Buffer, old_log_file.Buffer, log_file.Length) != log_file.Length ||
976  (!log_handle && log_file.Length > 0) || (old_debug_log_level == 0 && debug_log_level > 0) || (old_debug_log_level > 0 && debug_log_level == 0))) {
977  if (log_handle) {
978  ZwClose(log_handle);
979  log_handle = NULL;
980  }
981 
982  if (!comfo && log_file.Length > 0 && refresh && debug_log_level > 0) {
984 
986 
987  Status = ZwCreateFile(&log_handle, FILE_WRITE_DATA, &oa, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
989  if (!NT_SUCCESS(Status)) {
990  DbgPrint("ZwCreateFile returned %08x\n", Status);
991  log_handle = NULL;
992  }
993  }
994  }
995 
996  ExReleaseResourceLite(&log_lock);
997 
998  if (old_log_file.Buffer)
999  ExFreePool(old_log_file.Buffer);
1000 #endif
1001 
1002  ZwClose(h);
1003 }
1004 
1005 _Function_class_(WORKER_THREAD_ROUTINE)
1006 #ifdef __REACTOS__
1007 static void NTAPI registry_work_item(PVOID Parameter) {
1008 #else
1009 static void registry_work_item(PVOID Parameter) {
1010 #endif
1011  NTSTATUS Status;
1012  HANDLE regh = (HANDLE)Parameter;
1014 
1015  TRACE("registry changed\n");
1016 
1018 
1019  Status = ZwNotifyChangeKey(regh, NULL, (PVOID)&wqi, (PVOID)DelayedWorkQueue, &iosb, REG_NOTIFY_CHANGE_LAST_SET, TRUE, NULL, 0, TRUE);
1020  if (!NT_SUCCESS(Status))
1021  ERR("ZwNotifyChangeKey returned %08x\n", Status);
1022 }
1023 
1025  NTSTATUS Status;
1027 
1028  ExInitializeWorkItem(&wqi, registry_work_item, regh);
1029 
1030  Status = ZwNotifyChangeKey(regh, NULL, (PVOID)&wqi, (PVOID)DelayedWorkQueue, &iosb, REG_NOTIFY_CHANGE_LAST_SET, TRUE, NULL, 0, TRUE);
1031  if (!NT_SUCCESS(Status))
1032  ERR("ZwNotifyChangeKey returned %08x\n", Status);
1033 }
static void read_group_mappings(PUNICODE_STRING regpath)
Definition: registry.c:609
#define hex_digit(c)
Definition: btrfs_drv.h:1699
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static void read_mappings(PUNICODE_STRING regpath)
Definition: registry.c:531
struct _KEY_VALUE_BASIC_INFORMATION KEY_VALUE_BASIC_INFORMATION
static BOOL is_uuid(ULONG namelen, WCHAR *name)
Definition: registry.c:419
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define FILE_OPEN_IF
Definition: from_kernel.h:56
void add_user_mapping(WCHAR *sidstring, ULONG sidstringlength, UINT32 uid)
Definition: security.c:56
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:193
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define DbgPrint
Definition: loader.c:25
USHORT MaximumLength
Definition: env_spec_w32.h:370
struct _KEY_VALUE_FULL_INFORMATION KEY_VALUE_FULL_INFORMATION
static const BYTE us[]
Definition: encode.c:689
GLsizei const GLchar ** path
Definition: glext.h:7234
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
WORK_QUEUE_ITEM wqi
Definition: registry.c:32
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
struct _KEY_BASIC_INFORMATION KEY_BASIC_INFORMATION
UINT32 no_pnp
Definition: btrfs.c:83
void watch_registry(HANDLE regh)
Definition: registry.c:1024
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define is_hex(c)
Definition: registry.c:417
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1434
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
GLuint GLuint end
Definition: gl.h:1545
UINT32 mount_readonly
Definition: btrfs.c:82
#define BTRFS_COMPRESSION_ZSTD
Definition: btrfs.h:61
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
UINT32 mount_max_inline
Definition: btrfs.c:76
_In_ PVOID Parameter
Definition: ldrtypes.h:240
#define InsertTailList(ListHead, Entry)
NTSTATUS registry_mark_volume_mounted(BTRFS_UUID *uuid)
Definition: registry.c:229
UNICODE_STRING name
Definition: registry.c:437
GLint namelen
Definition: glext.h:7232
PSID sid
Definition: btrfs_drv.h:871
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define FILE_SHARE_READ
Definition: compat.h:125
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
UINT32 mount_no_barrier
Definition: btrfs.c:78
static void reset_subkeys(HANDLE h, PUNICODE_STRING reg_path)
Definition: registry.c:441
UINT32 mount_compress_type
Definition: btrfs.c:72
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:86
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
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
PSID sid
Definition: btrfs_drv.h:865
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
UINT32 mount_zlib_level
Definition: btrfs.c:73
unsigned int UINT32
unsigned int BOOL
Definition: ntddk_ex.h:94
static NTSTATUS registry_mark_volume_unmounted_path(PUNICODE_STRING path)
Definition: registry.c:293
UINT32 mount_allow_degraded
Definition: btrfs.c:81
NTSTATUS registry_mark_volume_unmounted(BTRFS_UUID *uuid)
Definition: registry.c:372
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
smooth NULL
Definition: ftsmooth.c:416
#define REG_NOTIFY_CHANGE_LAST_SET
Definition: winreg.h:40
UINT32 mount_clear_cache
Definition: btrfs.c:80
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
GLuint index
Definition: glext.h:6031
#define FILE_WRITE_DATA
Definition: nt_native.h:631
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
UINT32 mount_compress
Definition: btrfs.c:70
GLuint GLfloat * val
Definition: glext.h:7180
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 REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
BOOLEAN NTAPI FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1, IN PCUNICODE_STRING Name2, IN BOOLEAN IgnoreCase, IN PCWCH UpcaseTable OPTIONAL)
Definition: name.c:296
UINT32 mount_skip_balance
Definition: btrfs.c:77
#define TRACE(s)
Definition: solgame.cpp:4
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
GLsizeiptr size
Definition: glext.h:5919
if(!(yy_init))
Definition: macro.lex.yy.c:714
ERESOURCE mapping_lock
Definition: btrfs.c:93
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
ZSTDLIB_API int ZSTD_maxCLevel(void)
PVOID HANDLE
Definition: typedefs.h:71
unsigned long DWORD
Definition: ntddk_ex.h:95
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1954
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
LIST_ENTRY gid_map_list
Definition: btrfs.c:66
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
NTSTATUS registry_load_volume_options(device_extension *Vcb)
Definition: registry.c:36
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
LIST_ENTRY uid_map_list
Definition: btrfs.c:66
#define index(s, c)
Definition: various.h:29
UNICODE_STRING log_device
Definition: btrfs.c:85
static const WCHAR L[]
Definition: oid.c:1250
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
UINT32 debug_log_level
Definition: btrfs.c:69
UNICODE_STRING registry_path
Definition: btrfs.c:85
Definition: typedefs.h:117
UINT32 mount_flush_interval
Definition: btrfs.c:75
void add_group_mapping(WCHAR *sidstring, ULONG sidstringlength, UINT32 gid)
Definition: security.c:145
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
UNICODE_STRING log_file
Definition: btrfs.c:85
unsigned short USHORT
Definition: pedump.c:61
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_Function_class_(WORKER_THREAD_ROUTINE)
Definition: registry.c:1005
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
Definition: services.c:325
static void get_registry_value(HANDLE h, WCHAR *string, ULONG type, void *val, ULONG size)
Definition: registry.c:712
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
UINT32 mount_zstd_level
Definition: btrfs.c:74
void read_registry(PUNICODE_STRING regpath, BOOL refresh)
Definition: registry.c:763
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG const UNICODE_STRING ULONG PULONG dispos
Definition: reg.c:130
Definition: name.c:36
ULONG ERESOURCE
Definition: env_spec_w32.h:594
Definition: msctf.idl:510
#define REG_QWORD
Definition: sdbapi.c:597
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
LIST_ENTRY list_entry
Definition: registry.c:438
ROSDATA VSC_LPWSTR key_names[]
Definition: kbda1.c:262
static const WCHAR option_mounted[]
Definition: registry.c:34
unsigned long long UINT64
UINT32 mount_no_trim
Definition: btrfs.c:79
return STATUS_SUCCESS
Definition: btrfs.c:2745
unsigned char UINT8
#define REG_DWORD
Definition: sdbapi.c:596
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
UINT32 mount_compress_force
Definition: btrfs.c:71
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define DELETE
Definition: nt_native.h:57
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define REG_SZ
Definition: layer.c:22