ReactOS  0.4.14-dev-604-gcfdd483
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 %08x\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 %08x\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 %08x\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 %08x\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 %08x\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 %08x\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 %08x\n", Status);
357  goto end2;
358  }
359  } else {
360  Status = ZwDeleteKey(h);
361  if (!NT_SUCCESS(Status)) {
362  ERR("ZwDeleteKey returned %08x\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 %08x\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", 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 %08x\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 %08x\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 %08x\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 %u = %.*S = %u\n", i, 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 %08x\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 %u = %.*S = %u\n", i, 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  WCHAR* builtin_users = L"S-1-5-32-545";
689  UNICODE_STRING us2;
690  DWORD val;
691 
692  // If we're creating the key for the first time, we add a default mapping of
693  // BUILTIN\Users to gid 100, which ought to correspond to the "users" group on Linux.
694 
695  us2.Length = us2.MaximumLength = sizeof(builtin_users) - sizeof(WCHAR);
697 
698  if (us2.Buffer) {
699  RtlCopyMemory(us2.Buffer, builtin_users, us2.Length);
700 
701  val = 100;
702  Status = ZwSetValueKey(h, &us2, 0, REG_DWORD, &val, sizeof(DWORD));
703  if (!NT_SUCCESS(Status)) {
704  ERR("ZwSetValueKey returned %08x\n", Status);
705  ZwClose(h);
706  return;
707  }
708 
709  add_group_mapping(us2.Buffer, us2.Length / sizeof(WCHAR), val);
710 
711  ExFreePool(us2.Buffer);
712  }
713  }
714 
715  ZwClose(h);
716 }
717 
718 static void get_registry_value(HANDLE h, WCHAR* string, ULONG type, void* val, ULONG size) {
719  ULONG kvfilen;
723 
724  RtlInitUnicodeString(&us, string);
725 
726  kvfi = NULL;
727  kvfilen = 0;
728  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
729 
730  if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
731  kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
732 
733  if (!kvfi) {
734  ERR("out of memory\n");
735  ZwClose(h);
736  return;
737  }
738 
739  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
740 
741  if (NT_SUCCESS(Status)) {
742  if (kvfi->Type == type && kvfi->DataLength >= size) {
743  RtlCopyMemory(val, ((uint8_t*)kvfi) + kvfi->DataOffset, size);
744  } else {
745  Status = ZwDeleteValueKey(h, &us);
746  if (!NT_SUCCESS(Status)) {
747  ERR("ZwDeleteValueKey returned %08x\n", Status);
748  }
749 
750  Status = ZwSetValueKey(h, &us, 0, type, val, size);
751  if (!NT_SUCCESS(Status)) {
752  ERR("ZwSetValueKey returned %08x\n", Status);
753  }
754  }
755  }
756 
757  ExFreePool(kvfi);
758  } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
759  Status = ZwSetValueKey(h, &us, 0, type, val, size);
760 
761  if (!NT_SUCCESS(Status)) {
762  ERR("ZwSetValueKey returned %08x\n", Status);
763  }
764  } else {
765  ERR("ZwQueryValueKey returned %08x\n", Status);
766  }
767 }
768 
769 void read_registry(PUNICODE_STRING regpath, bool refresh) {
772  HANDLE h;
773  ULONG dispos;
774 #ifdef _DEBUG
776  ULONG kvfilen, old_debug_log_level = debug_log_level;
777  UNICODE_STRING us, old_log_file, old_log_device;
778 
779  static const WCHAR def_log_file[] = L"\\??\\C:\\btrfs.log";
780 #endif
781 
783 
784  read_mappings(regpath);
785  read_group_mappings(regpath);
786 
788 
790 
792 
793  if (!NT_SUCCESS(Status)) {
794  ERR("ZwCreateKey returned %08x\n", Status);
795  return;
796  }
797 
798  if (!refresh)
799  reset_subkeys(h, regpath);
800 
815 
816  if (!refresh)
817  get_registry_value(h, L"NoPNP", REG_DWORD, &no_pnp, sizeof(no_pnp));
818 
819  if (mount_flush_interval == 0)
821 
822 #ifdef _DEBUG
823  get_registry_value(h, L"DebugLogLevel", REG_DWORD, &debug_log_level, sizeof(debug_log_level));
824 
825  RtlInitUnicodeString(&us, L"LogDevice");
826 
827  kvfi = NULL;
828  kvfilen = 0;
829  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
830 
831  old_log_device = log_device;
832 
835 
836  if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
837  kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
838 
839  if (!kvfi) {
840  ERR("out of memory\n");
841  ZwClose(h);
842  return;
843  }
844 
845  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
846 
847  if (NT_SUCCESS(Status)) {
848  if ((kvfi->Type == REG_SZ || kvfi->Type == REG_EXPAND_SZ) && kvfi->DataLength >= sizeof(WCHAR)) {
851 
852  if (!log_device.Buffer) {
853  ERR("out of memory\n");
854  ExFreePool(kvfi);
855  ZwClose(h);
856  return;
857  }
858 
859  RtlCopyMemory(log_device.Buffer, ((uint8_t*)kvfi) + kvfi->DataOffset, log_device.Length);
860 
861  if (log_device.Buffer[(log_device.Length / sizeof(WCHAR)) - 1] == 0)
862  log_device.Length -= sizeof(WCHAR);
863  } else {
864  ERR("LogDevice was type %u, length %u\n", kvfi->Type, kvfi->DataLength);
865 
866  Status = ZwDeleteValueKey(h, &us);
867  if (!NT_SUCCESS(Status)) {
868  ERR("ZwDeleteValueKey returned %08x\n", Status);
869  }
870  }
871  }
872 
873  ExFreePool(kvfi);
874  } else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
875  ERR("ZwQueryValueKey returned %08x\n", Status);
876  }
877 
878  ExAcquireResourceExclusiveLite(&log_lock, true);
879 
880  if (refresh && (log_device.Length != old_log_device.Length || RtlCompareMemory(log_device.Buffer, old_log_device.Buffer, log_device.Length) != log_device.Length ||
881  (!comfo && log_device.Length > 0) || (old_debug_log_level == 0 && debug_log_level > 0) || (old_debug_log_level > 0 && debug_log_level == 0))) {
882  if (comfo)
883  ObDereferenceObject(comfo);
884 
885  if (log_handle) {
886  ZwClose(log_handle);
887  log_handle = NULL;
888  }
889 
890  comfo = NULL;
891  comdo = NULL;
892 
893  if (log_device.Length > 0 && debug_log_level > 0) {
895  if (!NT_SUCCESS(Status))
896  DbgPrint("IoGetDeviceObjectPointer returned %08x\n", Status);
897  }
898  }
899 
900  ExReleaseResourceLite(&log_lock);
901 
902  if (old_log_device.Buffer)
903  ExFreePool(old_log_device.Buffer);
904 
905  RtlInitUnicodeString(&us, L"LogFile");
906 
907  kvfi = NULL;
908  kvfilen = 0;
909  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
910 
911  old_log_file = log_file;
912 
913  if ((Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW) && kvfilen > 0) {
914  kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
915 
916  if (!kvfi) {
917  ERR("out of memory\n");
918  ZwClose(h);
919  return;
920  }
921 
922  Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
923 
924  if (NT_SUCCESS(Status)) {
925  if ((kvfi->Type == REG_SZ || kvfi->Type == REG_EXPAND_SZ) && kvfi->DataLength >= sizeof(WCHAR)) {
928 
929  if (!log_file.Buffer) {
930  ERR("out of memory\n");
931  ExFreePool(kvfi);
932  ZwClose(h);
933  return;
934  }
935 
936  RtlCopyMemory(log_file.Buffer, ((uint8_t*)kvfi) + kvfi->DataOffset, log_file.Length);
937 
938  if (log_file.Buffer[(log_file.Length / sizeof(WCHAR)) - 1] == 0)
939  log_file.Length -= sizeof(WCHAR);
940  } else {
941  ERR("LogFile was type %u, length %u\n", kvfi->Type, kvfi->DataLength);
942 
943  Status = ZwDeleteValueKey(h, &us);
944  if (!NT_SUCCESS(Status))
945  ERR("ZwDeleteValueKey returned %08x\n", Status);
946 
947  log_file.Length = 0;
948  }
949  } else {
950  ERR("ZwQueryValueKey returned %08\n", Status);
951  log_file.Length = 0;
952  }
953 
954  ExFreePool(kvfi);
955  } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
956  Status = ZwSetValueKey(h, &us, 0, REG_SZ, (void*)def_log_file, sizeof(def_log_file));
957 
958  if (!NT_SUCCESS(Status))
959  ERR("ZwSetValueKey returned %08x\n", Status);
960 
961  log_file.Length = 0;
962  } else {
963  ERR("ZwQueryValueKey returned %08x\n", Status);
964  log_file.Length = 0;
965  }
966 
967  if (log_file.Length == 0) {
968  log_file.Length = log_file.MaximumLength = sizeof(def_log_file) - sizeof(WCHAR);
970 
971  if (!log_file.Buffer) {
972  ERR("out of memory\n");
973  ZwClose(h);
974  return;
975  }
976 
977  RtlCopyMemory(log_file.Buffer, def_log_file, log_file.Length);
978  }
979 
980  ExAcquireResourceExclusiveLite(&log_lock, true);
981 
982  if (refresh && (log_file.Length != old_log_file.Length || RtlCompareMemory(log_file.Buffer, old_log_file.Buffer, log_file.Length) != log_file.Length ||
983  (!log_handle && log_file.Length > 0) || (old_debug_log_level == 0 && debug_log_level > 0) || (old_debug_log_level > 0 && debug_log_level == 0))) {
984  if (log_handle) {
985  ZwClose(log_handle);
986  log_handle = NULL;
987  }
988 
989  if (!comfo && log_file.Length > 0 && refresh && debug_log_level > 0) {
991 
993 
994  Status = ZwCreateFile(&log_handle, FILE_WRITE_DATA, &oa, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
996  if (!NT_SUCCESS(Status)) {
997  DbgPrint("ZwCreateFile returned %08x\n", Status);
998  log_handle = NULL;
999  }
1000  }
1001  }
1002 
1003  ExReleaseResourceLite(&log_lock);
1004 
1005  if (old_log_file.Buffer)
1006  ExFreePool(old_log_file.Buffer);
1007 #endif
1008 
1009  ZwClose(h);
1010 }
1011 
1012 _Function_class_(WORKER_THREAD_ROUTINE)
1013 static void __stdcall registry_work_item(PVOID Parameter) {
1014  NTSTATUS Status;
1015  HANDLE regh = (HANDLE)Parameter;
1017 
1018  TRACE("registry changed\n");
1019 
1020  read_registry(&registry_path, true);
1021 
1022  Status = ZwNotifyChangeKey(regh, NULL, (PVOID)&wqi, (PVOID)DelayedWorkQueue, &iosb, REG_NOTIFY_CHANGE_LAST_SET, true, NULL, 0, true);
1023  if (!NT_SUCCESS(Status))
1024  ERR("ZwNotifyChangeKey returned %08x\n", Status);
1025 }
1026 
1028  NTSTATUS Status;
1030 
1031  ExInitializeWorkItem(&wqi, registry_work_item, regh);
1032 
1033  Status = ZwNotifyChangeKey(regh, NULL, (PVOID)&wqi, (PVOID)DelayedWorkQueue, &iosb, REG_NOTIFY_CHANGE_LAST_SET, true, NULL, 0, true);
1034  if (!NT_SUCCESS(Status))
1035  ERR("ZwNotifyChangeKey returned %08x\n", Status);
1036 }
static void read_group_mappings(PUNICODE_STRING regpath)
Definition: registry.c:615
#define hex_digit(c)
Definition: btrfs_drv.h:1725
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
#define true
Definition: stdbool.h:37
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 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:111
LONG NTSTATUS
Definition: precomp.h:26
struct _KEY_BASIC_INFORMATION KEY_BASIC_INFORMATION
void watch_registry(HANDLE regh)
Definition: registry.c:1027
uint32_t mount_max_inline
Definition: btrfs.c:82
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
uint32_t mount_clear_cache
Definition: btrfs.c:86
uint32_t mount_no_barrier
Definition: btrfs.c:84
#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:885
uint32_t debug_log_level
Definition: btrfs.c:75
_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
void read_registry(PUNICODE_STRING regpath, bool refresh)
Definition: registry.c:769
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:879
uint32_t mount_readonly
Definition: btrfs.c:88
uint32_t no_pnp
Definition: btrfs.c:90
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:79
#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:119
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:106
__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
#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
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
LIST_ENTRY gid_map_list
Definition: btrfs.c:72
#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:72
#define index(s, c)
Definition: various.h:29
UNICODE_STRING log_device
Definition: btrfs.c:92
static const WCHAR L[]
Definition: oid.c:1250
uint32_t mount_no_trim
Definition: btrfs.c:85
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
uint32_t mount_zstd_level
Definition: btrfs.c:80
UNICODE_STRING registry_path
Definition: btrfs.c:92
Definition: typedefs.h:117
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint32_t mount_compress_type
Definition: btrfs.c:78
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:92
unsigned short USHORT
Definition: pedump.c:61
uint32_t mount_no_root_dir
Definition: btrfs.c:89
#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:1012
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
uint32_t mount_skip_balance
Definition: btrfs.c:83
static void get_registry_value(HANDLE h, WCHAR *string, ULONG type, void *val, ULONG size)
Definition: registry.c:718
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
uint32_t mount_flush_interval
Definition: btrfs.c:81
uint32_t mount_allow_degraded
Definition: btrfs.c:87
UINT32 uint32_t
Definition: types.h:75
uint32_t mount_compress
Definition: btrfs.c:76
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:2938
#define REG_DWORD
Definition: sdbapi.c:596
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
uint32_t mount_compress_force
Definition: btrfs.c:77
#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