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