ReactOS  0.4.14-dev-593-g1793dcc
database.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2011-2012 ReactOS Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program 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 General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * COPYRIGHT: See COPYING in the top level directory
20  * PROJECT: ReactOS kernel
21  * FILE: drivers/filesystem/mountmgr/mountmgr.c
22  * PURPOSE: Mount Manager - remote/local database handler
23  * PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org)
24  */
25 
26 #include "mntmgr.h"
27 
28 #define NDEBUG
29 #include <debug.h>
30 
31 PWSTR DatabasePath = L"\\Registry\\Machine\\System\\MountedDevices";
32 PWSTR OfflinePath = L"\\Registry\\Machine\\System\\MountedDevices\\Offline";
33 
34 UNICODE_STRING RemoteDatabase = RTL_CONSTANT_STRING(L"\\System Volume Information\\MountPointManagerRemoteDatabase");
35 
36 /*
37  * @implemented
38  */
39 LONG
41 {
44  FILE_STANDARD_INFORMATION StandardInfo;
45 
46  /* Just query the size */
47  Status = ZwQueryInformationFile(Database,
49  &StandardInfo,
52  if (NT_SUCCESS(Status))
53  {
54  return StandardInfo.EndOfFile.LowPart;
55  }
56 
57  return 0;
58 }
59 
60 /*
61  * @implemented
62  */
66 {
69 
70  /* Get size to append data */
72 
73  return ZwWriteFile(Database, NULL, NULL, NULL,
75  Entry->EntrySize, &Size, NULL);
76 }
77 
78 /*
79  * @implemented
80  */
83 {
84  return ZwClose(Database);
85 }
86 
87 /*
88  * @implemented
89  */
92  IN LONG NewSize)
93 {
97  FILE_ALLOCATION_INFORMATION Allocation;
98 
99  EndOfFile.EndOfFile.QuadPart = NewSize;
100  Allocation.AllocationSize.QuadPart = NewSize;
101 
102  /* First set EOF */
103  Status = ZwSetInformationFile(Database,
104  &IoStatusBlock,
105  &EndOfFile,
108  if (NT_SUCCESS(Status))
109  {
110  /* And then, properly set allocation information */
111  Status = ZwSetInformationFile(Database,
112  &IoStatusBlock,
113  &Allocation,
116  }
117 
118  return Status;
119 }
120 
121 /*
122  * @implemented
123  */
127 {
133 
134  /* Get the entry at the given position */
135  ByteOffset.QuadPart = StartingOffset;
136  Status = ZwReadFile(Database,
137  NULL,
138  NULL,
139  NULL,
140  &IoStatusBlock,
141  &EntrySize,
142  sizeof(EntrySize),
143  &ByteOffset,
144  NULL);
145  if (!NT_SUCCESS(Status))
146  {
147  return NULL;
148  }
149 
150  /* If entry doesn't exist, truncate database */
151  if (!EntrySize)
152  {
154  return NULL;
155  }
156 
157  /* Allocate the entry */
159  if (!Entry)
160  {
161  return NULL;
162  }
163 
164  /* Effectively read the entry */
165  Status = ZwReadFile(Database,
166  NULL,
167  NULL,
168  NULL,
169  &IoStatusBlock,
170  Entry,
171  EntrySize,
172  &ByteOffset,
173  NULL);
174  /* If it fails or returns inconsistent data, drop it (= truncate) */
175  if (!NT_SUCCESS(Status) ||
177  (EntrySize < sizeof(DATABASE_ENTRY)) )
178  {
180  FreePool(Entry);
181  return NULL;
182  }
183 
184  /* Validate entry */
185  if (MAX(Entry->SymbolicNameOffset + Entry->SymbolicNameLength,
186  Entry->UniqueIdOffset + Entry->UniqueIdLength) > (LONG)EntrySize)
187  {
189  FreePool(Entry);
190  return NULL;
191  }
192 
193  return Entry;
194 }
195 
196 /*
197  * @implemented
198  */
199 NTSTATUS
201  IN LONG Offset,
203 {
207 
208  ByteOffset.QuadPart = Offset;
209  Status = ZwWriteFile(Database,
210  NULL,
211  NULL,
212  NULL,
213  &IoStatusBlock,
214  Entry,
215  Entry->EntrySize,
216  &ByteOffset,
217  NULL);
218  if (NT_SUCCESS(Status))
219  {
220  if (IoStatusBlock.Information < Entry->EntrySize)
221  {
223  }
224  }
225 
226  return Status;
227 }
228 
229 /*
230  * @implemented
231  */
232 NTSTATUS
235 {
236  ULONG EndSize;
237  PVOID TmpBuffer;
239  ULONG DatabaseSize;
242  LARGE_INTEGER EndEntriesOffset;
243 
244  /* First, get database size */
245  DatabaseSize = GetRemoteDatabaseSize(Database);
246  if (!DatabaseSize)
247  {
249  }
250 
251  /* Then, get the entry to remove */
253  if (!Entry)
254  {
256  }
257 
258  /* Validate parameters: ensure we won't get negative size */
259  if (Entry->EntrySize + StartingOffset > DatabaseSize)
260  {
261  /* If we get invalid parameters, truncate the whole database
262  * starting the wrong entry. We can't rely on the rest
263  */
264  FreePool(Entry);
266  }
267 
268  /* Now, get the size of the remaining entries (those after the one to remove) */
269  EndSize = DatabaseSize - Entry->EntrySize - StartingOffset;
270  /* Allocate a buffer big enough to hold them */
271  TmpBuffer = AllocatePool(EndSize);
272  if (!TmpBuffer)
273  {
274  FreePool(Entry);
276  }
277 
278  /* Get the offset of the entry right after the one to delete */
279  EndEntriesOffset.QuadPart = Entry->EntrySize + StartingOffset;
280  /* We don't need the entry any more */
281  FreePool(Entry);
282 
283  /* Read the ending entries */
284  Status = ZwReadFile(Database, NULL, NULL, NULL, &IoStatusBlock,
285  TmpBuffer, EndSize, &EndEntriesOffset, NULL);
286  if (!NT_SUCCESS(Status))
287  {
288  FreePool(TmpBuffer);
289  return Status;
290  }
291 
292  /* Ensure nothing went wrong - we don't want to corrupt the DB */
293  if (IoStatusBlock.Information != EndSize)
294  {
295  FreePool(TmpBuffer);
297  }
298 
299  /* Remove the entry */
301  if (!NT_SUCCESS(Status))
302  {
303  FreePool(TmpBuffer);
304  return Status;
305  }
306 
307  /* Now, shift the ending entries to erase the entry */
308  EndEntriesOffset.QuadPart = StartingOffset;
309  Status = ZwWriteFile(Database, NULL, NULL, NULL, &IoStatusBlock,
310  TmpBuffer, EndSize, &EndEntriesOffset, NULL);
311 
312  FreePool(TmpBuffer);
313 
314  return Status;
315 }
316 
317 /*
318  * @implemented
319  */
320 NTSTATUS
321 NTAPI
326  IN PVOID Context,
328 {
329  PMOUNTDEV_UNIQUE_ID UniqueId = Context;
330 
333 
334  /* Ensure it matches, and delete */
335  if ((UniqueId->UniqueIdLength == ValueLength) &&
337  ValueLength))
338  {
340  DatabasePath,
341  ValueName);
342  }
343 
344  return STATUS_SUCCESS;
345 }
346 
347 /*
348  * @implemented
349  */
350 VOID
352  IN PMOUNTDEV_UNIQUE_ID UniqueId)
353 {
355 
358  QueryTable[0].Name = SymbolicLink->Buffer;
359 
361  DatabasePath,
362  QueryTable,
363  UniqueId,
364  NULL);
365 }
366 
367 /*
368  * @implemented
369  */
370 NTSTATUS
372 {
375 
376  /* Wait for 7 minutes */
377  Timeout.QuadPart = 0xFA0A1F00;
378  Status = KeWaitForSingleObject(&(DeviceExtension->RemoteDatabaseLock), Executive, KernelMode, FALSE, &Timeout);
379  if (Status != STATUS_TIMEOUT)
380  {
381  return Status;
382  }
383 
384  return STATUS_IO_TIMEOUT;
385 }
386 
387 /*
388  * @implemented
389  */
390 VOID
392 {
393  KeReleaseSemaphore(&(DeviceExtension->RemoteDatabaseLock), IO_NO_INCREMENT, 1, FALSE);
394 }
395 
396 /*
397  * @implemented
398  */
399 NTSTATUS
400 NTAPI
405  IN PVOID Context,
407 {
408  PMOUNTDEV_UNIQUE_ID IntUniqueId;
409  PMOUNTDEV_UNIQUE_ID * UniqueId;
410 
414 
415  /* Sanity check */
416  if (ValueLength >= 0x10000)
417  {
418  return STATUS_SUCCESS;
419  }
420 
421  /* Allocate the Unique ID */
422  IntUniqueId = AllocatePool(sizeof(UniqueId) + ValueLength);
423  if (IntUniqueId)
424  {
425  /* Copy data & return */
426  IntUniqueId->UniqueIdLength = (USHORT)ValueLength;
427  RtlCopyMemory(&(IntUniqueId->UniqueId), ValueData, ValueLength);
428 
429  UniqueId = Context;
430  *UniqueId = IntUniqueId;
431  }
432 
433  return STATUS_SUCCESS;
434 }
435 
436 /*
437  * @implemented
438  */
439 NTSTATUS
442  OUT PMOUNTDEV_UNIQUE_ID * UniqueId)
443 {
445  PDEVICE_INFORMATION DeviceInformation;
447 
448  /* Query the unique ID */
452 
453  *UniqueId = NULL;
455  DatabasePath,
456  QueryTable,
457  UniqueId,
458  NULL);
459  /* Unique ID found, no need to go farther */
460  if (*UniqueId)
461  {
462  return STATUS_SUCCESS;
463  }
464 
465  /* Otherwise, find associate device information */
466  Status = FindDeviceInfo(DeviceExtension, SymbolicName, FALSE, &DeviceInformation);
467  if (!NT_SUCCESS(Status))
468  {
469  return Status;
470  }
471 
472  *UniqueId = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
473  if (!*UniqueId)
474  {
476  }
477 
478  /* Return this unique ID (better than nothing) */
479  (*UniqueId)->UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength;
480  RtlCopyMemory(&((*UniqueId)->UniqueId), &(DeviceInformation->UniqueId->UniqueId), (*UniqueId)->UniqueIdLength);
481 
482  return STATUS_SUCCESS;
483 }
484 
485 /*
486  * @implemented
487  */
488 NTSTATUS
490  IN PDATABASE_ENTRY DatabaseEntry)
491 {
494  PLIST_ENTRY NextEntry;
495  UNICODE_STRING SymbolicString;
496  PDEVICE_INFORMATION DeviceInformation;
497 
498  /* Create symbolic name from database entry */
499  SymbolicName = AllocatePool(DatabaseEntry->SymbolicNameLength + sizeof(WCHAR));
500  if (!SymbolicName)
501  {
503  }
504 
506  (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset),
507  DatabaseEntry->SymbolicNameLength);
508  SymbolicName[DatabaseEntry->SymbolicNameLength / sizeof(WCHAR)] = UNICODE_NULL;
509 
510  /* Associate the unique ID with the name from remote database */
512  DatabasePath,
513  SymbolicName,
514  REG_BINARY,
515  (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
516  DatabaseEntry->UniqueIdLength);
518 
519  /* Reget symbolic name */
520  SymbolicString.Length = DatabaseEntry->SymbolicNameLength;
521  SymbolicString.MaximumLength = DatabaseEntry->SymbolicNameLength;
522  SymbolicString.Buffer = (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
523 
524  /* Find the device using this unique ID */
525  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
526  NextEntry != &(DeviceExtension->DeviceListHead);
527  NextEntry = NextEntry->Flink)
528  {
529  DeviceInformation = CONTAINING_RECORD(NextEntry,
531  DeviceListEntry);
532 
533  if (DeviceInformation->UniqueId->UniqueIdLength != DatabaseEntry->UniqueIdLength)
534  {
535  continue;
536  }
537 
538  if (RtlCompareMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
539  DeviceInformation->UniqueId->UniqueId,
540  DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
541  {
542  break;
543  }
544  }
545 
546  /* If found, create a mount point */
547  if (NextEntry != &(DeviceExtension->DeviceListHead))
548  {
549  MountMgrCreatePointWorker(DeviceExtension, &SymbolicString, &(DeviceInformation->DeviceName));
550  }
551 
552  return Status;
553 }
554 
555 /*
556  * @implemented
557  */
558 VOID
559 NTAPI
561 {
562  ULONG Offset;
566  PMOUNTDEV_UNIQUE_ID UniqueId;
567  PDATABASE_ENTRY DatabaseEntry;
568  HANDLE DatabaseHandle, Handle;
571  PDEVICE_INFORMATION ListDeviceInfo;
572  PLIST_ENTRY Entry, EntryInfo, NextEntry;
573  PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
574  BOOLEAN HardwareErrors, Restart, FailedFinding;
575  WCHAR FileNameBuffer[0x8], SymbolicNameBuffer[100];
577  FILE_REPARSE_POINT_INFORMATION ReparsePointInformation, SavedReparsePointInformation;
578  PDEVICE_EXTENSION DeviceExtension = ((PRECONCILE_WORK_ITEM_CONTEXT)Parameter)->DeviceExtension;
579  PDEVICE_INFORMATION DeviceInformation = ((PRECONCILE_WORK_ITEM_CONTEXT)Parameter)->DeviceInformation;
580 
581  /* We're unloading, do nothing */
582  if (Unloading)
583  {
584  return;
585  }
586 
587  /* Lock remote DB */
588  if (!NT_SUCCESS(WaitForRemoteDatabaseSemaphore(DeviceExtension)))
589  {
590  return;
591  }
592 
593  /* Recheck for unloading */
594  if (Unloading)
595  {
596  goto ReleaseRDS;
597  }
598 
599  /* Find the DB to reconcile */
600  KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
601  for (Entry = DeviceExtension->DeviceListHead.Flink;
602  Entry != &DeviceExtension->DeviceListHead;
603  Entry = Entry->Flink)
604  {
605  ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
606  if (ListDeviceInfo == DeviceInformation)
607  {
608  break;
609  }
610  }
611 
612  /* If not found, or if removable, bail out */
613  if (Entry == &DeviceExtension->DeviceListHead || DeviceInformation->Removable)
614  {
615  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
616  goto ReleaseRDS;
617  }
618 
619  /* Get our device object */
621  if (!NT_SUCCESS(Status))
622  {
623  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
624  goto ReleaseRDS;
625  }
626 
627  /* Mark mounted only if not unloading */
629  {
630  InterlockedExchangeAdd(&ListDeviceInfo->MountState, 1);
631  }
632 
634 
635  /* Force default: no DB, and need for reconcile */
636  DeviceInformation->NeedsReconcile = TRUE;
637  DeviceInformation->NoDatabase = TRUE;
638  FailedFinding = FALSE;
639 
640  /* Remove any associated device that refers to the DB to reconcile */
641  for (Entry = DeviceExtension->DeviceListHead.Flink;
642  Entry != &DeviceExtension->DeviceListHead;
643  Entry = Entry->Flink)
644  {
645  ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
646 
647  EntryInfo = ListDeviceInfo->AssociatedDevicesHead.Flink;
648  while (EntryInfo != &ListDeviceInfo->AssociatedDevicesHead)
649  {
650  AssociatedDevice = CONTAINING_RECORD(EntryInfo, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
651  NextEntry = EntryInfo->Flink;
652 
653  if (AssociatedDevice->DeviceInformation == DeviceInformation)
654  {
655  RemoveEntryList(&AssociatedDevice->AssociatedDevicesEntry);
656  FreePool(AssociatedDevice->String.Buffer);
657  FreePool(AssociatedDevice);
658  }
659 
660  EntryInfo = NextEntry;
661  }
662  }
663 
664  /* Open the remote database */
665  DatabaseHandle = OpenRemoteDatabase(DeviceInformation, FALSE);
666 
667  /* Prepare a string with reparse point index */
668  ReparseFile.Length = DeviceInformation->DeviceName.Length + ReparseIndex.Length;
669  ReparseFile.MaximumLength = ReparseFile.Length + sizeof(UNICODE_NULL);
670  ReparseFile.Buffer = AllocatePool(ReparseFile.MaximumLength);
671  if (ReparseFile.Buffer == NULL)
672  {
673  if (DatabaseHandle != 0)
674  {
675  CloseRemoteDatabase(DatabaseHandle);
676  }
677  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
678  goto ReleaseRDS;
679  }
680 
681  RtlCopyMemory(ReparseFile.Buffer, DeviceInformation->DeviceName.Buffer,
682  DeviceInformation->DeviceName.Length);
683  RtlCopyMemory((PVOID)((ULONG_PTR)ReparseFile.Buffer + DeviceInformation->DeviceName.Length),
685  ReparseFile.Buffer[ReparseFile.Length / sizeof(WCHAR)] = UNICODE_NULL;
686 
688  &ReparseFile,
690  NULL,
691  NULL);
692 
693  /* Open reparse point directory */
694  HardwareErrors = IoSetThreadHardErrorMode(FALSE);
698  &IoStatusBlock,
701  IoSetThreadHardErrorMode(HardwareErrors);
702 
703  FreePool(ReparseFile.Buffer);
704 
705  if (!NT_SUCCESS(Status))
706  {
707  if (DatabaseHandle != 0)
708  {
709  TruncateRemoteDatabase(DatabaseHandle, 0);
710  CloseRemoteDatabase(DatabaseHandle);
711  }
712  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
713  goto ReleaseRDS;
714  }
715 
716  /* Query reparse point information
717  * We only pay attention to mout point
718  */
720  FileName.Buffer = FileNameBuffer;
721  FileName.Length = sizeof(FileNameBuffer);
722  FileName.MaximumLength = sizeof(FileNameBuffer);
724  Status = ZwQueryDirectoryFile(Handle,
725  NULL,
726  NULL,
727  NULL,
728  &IoStatusBlock,
729  &ReparsePointInformation,
732  TRUE,
733  &FileName,
734  FALSE);
735  if (!NT_SUCCESS(Status))
736  {
737  ZwClose(Handle);
738  if (DatabaseHandle != 0)
739  {
740  TruncateRemoteDatabase(DatabaseHandle, 0);
741  CloseRemoteDatabase(DatabaseHandle);
742  }
743  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
744  goto ReleaseRDS;
745  }
746 
747  /* If we failed to open the remote DB previously,
748  * retry this time allowing migration (and thus, creation if required)
749  */
750  if (DatabaseHandle == 0)
751  {
752  DatabaseHandle = OpenRemoteDatabase(DeviceInformation, TRUE);
753  if (DatabaseHandle == 0)
754  {
755  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
756  goto ReleaseRDS;
757  }
758  }
759 
760  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
761 
762  /* Reset all the references to our DB entries */
763  Offset = 0;
764  for (;;)
765  {
766  DatabaseEntry = GetRemoteDatabaseEntry(DatabaseHandle, Offset);
767  if (DatabaseEntry == NULL)
768  {
769  break;
770  }
771 
772  DatabaseEntry->EntryReferences = 0;
773  Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
774  if (!NT_SUCCESS(Status))
775  {
776  FreePool(DatabaseEntry);
777  goto CloseReparse;
778  }
779 
780  Offset += DatabaseEntry->EntrySize;
781  FreePool(DatabaseEntry);
782  }
783 
784  /* Init string for QueryVolumeName call */
785  SymbolicName.MaximumLength = sizeof(SymbolicNameBuffer);
786  SymbolicName.Length = 0;
787  SymbolicName.Buffer = SymbolicNameBuffer;
788  Restart = TRUE;
789 
790  /* Start looping on reparse points */
791  for (;;)
792  {
793  RtlCopyMemory(&SavedReparsePointInformation, &ReparsePointInformation, sizeof(FILE_REPARSE_POINT_INFORMATION));
794  Status = ZwQueryDirectoryFile(Handle,
795  NULL,
796  NULL,
797  NULL,
798  &IoStatusBlock,
799  &ReparsePointInformation,
802  TRUE,
803  Restart ? &FileName : NULL,
804  Restart);
805  /* Restart only once */
806  if (Restart)
807  {
808  Restart = FALSE;
809  }
810  else
811  {
812  /* If we get the same one, we're done, bail out */
813  if (ReparsePointInformation.FileReference == SavedReparsePointInformation.FileReference &&
814  ReparsePointInformation.Tag == SavedReparsePointInformation.Tag)
815  {
816  break;
817  }
818  }
819 
820  /* If querying failed, or if onloading, or if not returning mount points, bail out */
821  if (!NT_SUCCESS(Status) || Unloading || ReparsePointInformation.Tag != IO_REPARSE_TAG_MOUNT_POINT)
822  {
823  break;
824  }
825 
826  /* Get the volume name associated to the mount point */
827  Status = QueryVolumeName(Handle, &ReparsePointInformation, 0, &SymbolicName, &VolumeName);
828  if (!NT_SUCCESS(Status))
829  {
830  continue;
831  }
832 
833  /* Browse the DB to find the name */
834  Offset = 0;
835  for (;;)
836  {
837  UNICODE_STRING DbName;
838 
839  DatabaseEntry = GetRemoteDatabaseEntry(DatabaseHandle, Offset);
840  if (DatabaseEntry == NULL)
841  {
842  break;
843  }
844 
845  DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
846  DbName.Length = DbName.MaximumLength;
847  DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
848  /* Found, we're done! */
849  if (RtlEqualUnicodeString(&DbName, &SymbolicName, TRUE))
850  {
851  break;
852  }
853 
854  Offset += DatabaseEntry->EntrySize;
855  FreePool(DatabaseEntry);
856  }
857 
858  /* If we found the mount point.... */
859  if (DatabaseEntry != NULL)
860  {
861  /* If it was referenced, reference it once more and update to remote */
862  if (DatabaseEntry->EntryReferences)
863  {
864  ++DatabaseEntry->EntryReferences;
865  Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
866  if (!NT_SUCCESS(Status))
867  {
868  goto FreeDBEntry;
869  }
870 
871  FreePool(DatabaseEntry);
872  }
873  else
874  {
875  /* Query the Unique ID associated to that mount point in case it changed */
876  KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
877  Status = QueryUniqueIdFromMaster(DeviceExtension, &SymbolicName, &UniqueId);
878  if (!NT_SUCCESS(Status))
879  {
880  /* If we failed doing so, reuse the old Unique ID and push it to master */
881  Status = WriteUniqueIdToMaster(DeviceExtension, DatabaseEntry);
882  if (!NT_SUCCESS(Status))
883  {
884  goto ReleaseDeviceLock;
885  }
886 
887  /* And then, reference & write the entry */
888  ++DatabaseEntry->EntryReferences;
889  Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
890  if (!NT_SUCCESS(Status))
891  {
892  goto ReleaseDeviceLock;
893  }
894 
895  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
896  FreePool(DatabaseEntry);
897  }
898  /* If the Unique ID didn't change */
899  else if (UniqueId->UniqueIdLength == DatabaseEntry->UniqueIdLength &&
900  RtlCompareMemory(UniqueId->UniqueId,
901  (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
902  UniqueId->UniqueIdLength) == UniqueId->UniqueIdLength)
903  {
904  /* Reference the entry, and update to remote */
905  ++DatabaseEntry->EntryReferences;
906  Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
907  if (!NT_SUCCESS(Status))
908  {
909  goto FreeUniqueId;
910  }
911 
912  FreePool(UniqueId);
913  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
914  FreePool(DatabaseEntry);
915  }
916  /* Would, by chance, the Unique ID be present elsewhere? */
917  else if (IsUniqueIdPresent(DeviceExtension, DatabaseEntry))
918  {
919  /* Push the ID to master */
920  Status = WriteUniqueIdToMaster(DeviceExtension, DatabaseEntry);
921  if (!NT_SUCCESS(Status))
922  {
923  goto FreeUniqueId;
924  }
925 
926  /* And then, reference & write the entry */
927  ++DatabaseEntry->EntryReferences;
928  Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
929  if (!NT_SUCCESS(Status))
930  {
931  goto FreeUniqueId;
932  }
933 
934  FreePool(UniqueId);
935  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
936  FreePool(DatabaseEntry);
937  }
938  else
939  {
940  /* OK, at that point, we're facing a totally unknown unique ID
941  * So, get rid of the old entry, and recreate a new one with
942  * the know unique ID
943  */
944  Status = DeleteRemoteDatabaseEntry(DatabaseHandle, Offset);
945  if (!NT_SUCCESS(Status))
946  {
947  goto FreeUniqueId;
948  }
949 
950  FreePool(DatabaseEntry);
951  /* Allocate a new entry big enough */
952  DatabaseEntry = AllocatePool(UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY));
953  if (DatabaseEntry == NULL)
954  {
955  goto FreeUniqueId;
956  }
957 
958  /* Configure it */
959  DatabaseEntry->EntrySize = UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY);
960  DatabaseEntry->EntryReferences = 1;
961  DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
962  DatabaseEntry->SymbolicNameLength = SymbolicName.Length;
963  DatabaseEntry->UniqueIdOffset = SymbolicName.Length + sizeof(DATABASE_ENTRY);
964  DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
965  RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset), SymbolicName.Buffer, DatabaseEntry->SymbolicNameLength);
966  RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
967 
968  /* And write it remotely */
969  Status = AddRemoteDatabaseEntry(DatabaseHandle, DatabaseEntry);
970  if (!NT_SUCCESS(Status))
971  {
972  FreePool(DatabaseEntry);
973  goto FreeUniqueId;
974  }
975 
976  FreePool(UniqueId);
977  FreePool(DatabaseEntry);
978  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
979  }
980  }
981  }
982  else
983  {
984  /* We failed finding it remotely
985  * So, let's allocate a new remote DB entry
986  */
987  KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
988  /* To be able to do so, we need the device Unique ID, ask master */
989  Status = QueryUniqueIdFromMaster(DeviceExtension, &SymbolicName, &UniqueId);
990  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
991  if (NT_SUCCESS(Status))
992  {
993  /* Allocate a new entry big enough */
994  DatabaseEntry = AllocatePool(UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY));
995  if (DatabaseEntry != NULL)
996  {
997  /* Configure it */
998  DatabaseEntry->EntrySize = UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY);
999  DatabaseEntry->EntryReferences = 1;
1000  DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
1001  DatabaseEntry->SymbolicNameLength = SymbolicName.Length;
1002  DatabaseEntry->UniqueIdOffset = SymbolicName.Length + sizeof(DATABASE_ENTRY);
1003  DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
1004  RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset), SymbolicName.Buffer, DatabaseEntry->SymbolicNameLength);
1005  RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
1006 
1007  /* And write it remotely */
1008  Status = AddRemoteDatabaseEntry(DatabaseHandle, DatabaseEntry);
1009  FreePool(DatabaseEntry);
1010  FreePool(UniqueId);
1011 
1012  if (!NT_SUCCESS(Status))
1013  {
1014  goto FreeVolume;
1015  }
1016  }
1017  else
1018  {
1019  FreePool(UniqueId);
1020  }
1021  }
1022  }
1023 
1024  /* Find info about the device associated associated with the mount point */
1025  KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1026  Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &ListDeviceInfo);
1027  if (!NT_SUCCESS(Status))
1028  {
1029  FailedFinding = TRUE;
1031  }
1032  else
1033  {
1034  /* Associate the device with the currrent DB */
1035  AssociatedDevice = AllocatePool(sizeof(ASSOCIATED_DEVICE_ENTRY));
1036  if (AssociatedDevice == NULL)
1037  {
1039  }
1040  else
1041  {
1042  AssociatedDevice->DeviceInformation = DeviceInformation;
1043  AssociatedDevice->String.Length = VolumeName.Length;
1044  AssociatedDevice->String.MaximumLength = VolumeName.MaximumLength;
1045  AssociatedDevice->String.Buffer = VolumeName.Buffer;
1046  InsertTailList(&ListDeviceInfo->AssociatedDevicesHead, &AssociatedDevice->AssociatedDevicesEntry);
1047  }
1048 
1049  /* If we don't have to skip notifications, notify */
1050  if (!ListDeviceInfo->SkipNotifications)
1051  {
1052  PostOnlineNotification(DeviceExtension, &ListDeviceInfo->SymbolicName);
1053  }
1054  }
1055 
1056  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1057  }
1058 
1059  /* We don't need mount points any longer */
1060  ZwClose(Handle);
1061 
1062  /* Look for the DB again */
1063  KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1064  for (Entry = DeviceExtension->DeviceListHead.Flink;
1065  Entry != &DeviceExtension->DeviceListHead;
1066  Entry = Entry->Flink)
1067  {
1068  ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
1069  if (ListDeviceInfo == DeviceInformation)
1070  {
1071  break;
1072  }
1073  }
1074 
1075  if (Entry == &DeviceExtension->DeviceListHead)
1076  {
1077  ListDeviceInfo = NULL;
1078  }
1079 
1080  /* Start the pruning loop */
1081  Offset = 0;
1082  for (;;)
1083  {
1084  /* Get the entry */
1085  DatabaseEntry = GetRemoteDatabaseEntry(DatabaseHandle, Offset);
1086  if (DatabaseEntry == NULL)
1087  {
1088  break;
1089  }
1090 
1091  /* It's not referenced anylonger? Prune it */
1092  if (DatabaseEntry->EntryReferences == 0)
1093  {
1094  Status = DeleteRemoteDatabaseEntry(DatabaseHandle, Offset);
1095  if (!NT_SUCCESS(Status))
1096  {
1097  FreePool(DatabaseEntry);
1098  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1099  goto CloseRDB;
1100  }
1101  }
1102  /* Update the Unique IDs to reflect the changes we might have done previously */
1103  else
1104  {
1105  if (ListDeviceInfo != NULL)
1106  {
1107  UpdateReplicatedUniqueIds(ListDeviceInfo, DatabaseEntry);
1108  }
1109 
1110  Offset += DatabaseEntry->EntrySize;
1111  }
1112 
1113  FreePool(DatabaseEntry);
1114  }
1115 
1116  /* We do have a DB now :-) */
1117  if (ListDeviceInfo != NULL && !FailedFinding)
1118  {
1119  DeviceInformation->NoDatabase = FALSE;
1120  }
1121 
1122  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1123 
1124  goto CloseRDB;
1125 
1126 FreeUniqueId:
1127  FreePool(UniqueId);
1128 ReleaseDeviceLock:
1129  KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1130 FreeDBEntry:
1131  FreePool(DatabaseEntry);
1132 FreeVolume:
1134 CloseReparse:
1135  ZwClose(Handle);
1136 CloseRDB:
1137  CloseRemoteDatabase(DatabaseHandle);
1138 ReleaseRDS:
1139  ReleaseRemoteDatabaseSemaphore(DeviceExtension);
1140  return;
1141 }
1142 
1143 /*
1144  * @implemented
1145  */
1146 VOID
1147 NTAPI
1149  IN PVOID Context)
1150 {
1151  ULONG i;
1152  KEVENT Event;
1153  KIRQL OldIrql;
1154  NTSTATUS Status;
1155  HANDLE SafeEvent;
1158  PRECONCILE_WORK_ITEM WorkItem;
1159  PDEVICE_EXTENSION DeviceExtension;
1161 
1163 
1165  &SafeVolumes,
1167  NULL,
1168  NULL);
1170  Timeout.QuadPart = -10000000LL; /* Wait for 1 second */
1171 
1172  /* Wait as long as possible for clearance from autochk
1173  * We will write remote databases only if it is safe
1174  * to access volumes.
1175  * First, given we start before SMSS, wait for the
1176  * event creation.
1177  */
1178  i = 0;
1179  do
1180  {
1181  /* If we started to shutdown, stop waiting forever and jump to last attempt */
1182  if (Unloading)
1183  {
1184  i = 999;
1185  }
1186  else
1187  {
1188  /* Attempt to open the event */
1190  if (NT_SUCCESS(Status))
1191  {
1192  break;
1193  }
1194 
1195  /* Wait a bit to give SMSS a chance to create the event */
1197  }
1198 
1199  ++i;
1200  }
1201  while (i < 1000);
1202 
1203  /* We managed to open the event, wait until autochk signals it */
1204  if (i < 1000)
1205  {
1206  do
1207  {
1208  Status = ZwWaitForSingleObject(SafeEvent, FALSE, &Timeout);
1209  }
1210  while (Status == STATUS_TIMEOUT && !Unloading);
1211 
1212  ZwClose(SafeEvent);
1213  }
1214 
1215  DeviceExtension = Context;
1216 
1217  InterlockedExchange(&(DeviceExtension->WorkerThreadStatus), 1);
1218 
1219  /* Acquire workers lock */
1220  KeWaitForSingleObject(&(DeviceExtension->WorkerSemaphore), Executive, KernelMode, FALSE, NULL);
1221 
1222  KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
1223 
1224  /* Ensure there are workers */
1225  while (!IsListEmpty(&(DeviceExtension->WorkerQueueListHead)))
1226  {
1227  /* Unqueue a worker */
1228  Entry = RemoveHeadList(&(DeviceExtension->WorkerQueueListHead));
1229  WorkItem = CONTAINING_RECORD(Entry,
1231  WorkerQueueListEntry);
1232 
1233  KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
1234 
1235  /* Call it */
1236  WorkItem->WorkerRoutine(WorkItem->Context);
1237 
1238  IoFreeWorkItem(WorkItem->WorkItem);
1239  FreePool(WorkItem);
1240 
1241  if (InterlockedDecrement(&(DeviceExtension->WorkerReferences)) < 0)
1242  {
1243  return;
1244  }
1245 
1246  KeWaitForSingleObject(&(DeviceExtension->WorkerSemaphore), Executive, KernelMode, FALSE, NULL);
1247  KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
1248  }
1249  KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
1250 
1251  InterlockedDecrement(&(DeviceExtension->WorkerReferences));
1252 
1253  /* Reset event */
1255 }
1256 
1257 /*
1258  * @implemented
1259  */
1260 NTSTATUS
1262  IN PRECONCILE_WORK_ITEM WorkItem,
1263  IN PVOID Context)
1264 {
1265  KIRQL OldIrql;
1266 
1267  WorkItem->Context = Context;
1268 
1269  /* When called, lock is already acquired */
1270 
1271  /* If noone (-1 as references), start to work */
1272  if (InterlockedIncrement(&(DeviceExtension->WorkerReferences)) == 0)
1273  {
1274  IoQueueWorkItem(WorkItem->WorkItem, WorkerThread, DelayedWorkQueue, DeviceExtension);
1275  }
1276 
1277  /* Otherwise queue worker for delayed execution */
1278  KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
1279  InsertTailList(&(DeviceExtension->WorkerQueueListHead),
1280  &(WorkItem->WorkerQueueListEntry));
1281  KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
1282 
1283  KeReleaseSemaphore(&(DeviceExtension->WorkerSemaphore), IO_NO_INCREMENT, 1, FALSE);
1284 
1285  return STATUS_SUCCESS;
1286 }
1287 
1288 /*
1289  * @implemented
1290  */
1291 NTSTATUS
1293  IN PFILE_REPARSE_POINT_INFORMATION ReparsePointInformation,
1297 {
1298  HANDLE Handle;
1299  NTSTATUS Status;
1300  ULONG NeededLength;
1303  PFILE_NAME_INFORMATION FileNameInfo;
1304  PREPARSE_DATA_BUFFER ReparseDataBuffer;
1305 
1306  UNREFERENCED_PARAMETER(ReparsePointInformation);
1307 
1308  if (!FileName)
1309  {
1311  NULL,
1313  RootDirectory,
1314  NULL);
1315  }
1316  else
1317  {
1319  FileName,
1321  NULL,
1322  NULL);
1323  }
1324 
1325  /* Open volume */
1329  &IoStatusBlock,
1333  if (!NT_SUCCESS(Status))
1334  {
1335  return Status;
1336  }
1337 
1338  /* Get the reparse point data */
1339  ReparseDataBuffer = AllocatePool(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1340  if (!ReparseDataBuffer)
1341  {
1342  ZwClose(Handle);
1344  }
1345 
1347  0,
1348  NULL,
1349  NULL,
1350  &IoStatusBlock,
1352  NULL,
1353  0,
1354  ReparseDataBuffer,
1356  if (!NT_SUCCESS(Status))
1357  {
1358  FreePool(ReparseDataBuffer);
1359  ZwClose(Handle);
1360  return Status;
1361  }
1362 
1363  /* Check that name can fit in buffer */
1364  if (ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength + sizeof(UNICODE_NULL) > SymbolicName->MaximumLength)
1365  {
1366  FreePool(ReparseDataBuffer);
1367  ZwClose(Handle);
1368  return STATUS_BUFFER_TOO_SMALL;
1369  }
1370 
1371  /* Copy symbolic name */
1372  SymbolicName->Length = ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength;
1374  (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
1375  ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset),
1376  ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength);
1377 
1378  FreePool(ReparseDataBuffer);
1379 
1380  /* Name has to \ terminated */
1381  if (SymbolicName->Buffer[SymbolicName->Length / sizeof(WCHAR) - 1] != L'\\')
1382  {
1383  ZwClose(Handle);
1384  return STATUS_INVALID_PARAMETER;
1385  }
1386 
1387  /* So that we can delete it, and match mountmgr requirements */
1388  SymbolicName->Length -= sizeof(WCHAR);
1390 
1391  /* Also ensure it's really a volume name... */
1393  {
1394  ZwClose(Handle);
1395  return STATUS_INVALID_PARAMETER;
1396  }
1397 
1398  /* Now prepare to really get the name */
1399  FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + 2 * sizeof(WCHAR));
1400  if (!FileNameInfo)
1401  {
1402  ZwClose(Handle);
1404  }
1405 
1406  Status = ZwQueryInformationFile(Handle,
1407  &IoStatusBlock,
1408  FileNameInfo,
1409  sizeof(FILE_NAME_INFORMATION) + 2 * sizeof(WCHAR),
1412  {
1413  /* As expected... Reallocate with proper size */
1414  NeededLength = FileNameInfo->FileNameLength;
1415  FreePool(FileNameInfo);
1416 
1417  FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + NeededLength);
1418  if (!FileNameInfo)
1419  {
1420  ZwClose(Handle);
1422  }
1423 
1424  /* And query name */
1425  Status = ZwQueryInformationFile(Handle,
1426  &IoStatusBlock,
1427  FileNameInfo,
1428  sizeof(FILE_NAME_INFORMATION) + NeededLength,
1430  }
1431 
1432  ZwClose(Handle);
1433 
1434  if (!NT_SUCCESS(Status))
1435  {
1436  return Status;
1437  }
1438 
1439  /* Return the volume name */
1440  VolumeName->Length = (USHORT)FileNameInfo->FileNameLength;
1441  VolumeName->MaximumLength = (USHORT)FileNameInfo->FileNameLength + sizeof(WCHAR);
1443  if (!VolumeName->Buffer)
1444  {
1446  }
1447 
1448  RtlCopyMemory(VolumeName->Buffer, FileNameInfo->FileName, FileNameInfo->FileNameLength);
1449  VolumeName->Buffer[FileNameInfo->FileNameLength / sizeof(WCHAR)] = UNICODE_NULL;
1450 
1451  FreePool(FileNameInfo);
1452 
1453  return STATUS_SUCCESS;
1454 }
1455 
1456 /*
1457  * @implemented
1458  */
1459 VOID
1461  IN PDEVICE_INFORMATION DeviceInformation)
1462 {
1463  HANDLE Handle;
1464  NTSTATUS Status;
1468  PDEVICE_INFORMATION VolumeDeviceInformation;
1469  WCHAR FileNameBuffer[0x8], SymbolicNameBuffer[0x64];
1471  FILE_REPARSE_POINT_INFORMATION ReparsePointInformation, SavedReparsePointInformation;
1472 
1473  /* Removable devices don't have remote database on them */
1474  if (DeviceInformation->Removable)
1475  {
1476  return;
1477  }
1478 
1479  /* Prepare a string with reparse point index */
1480  ReparseFile.Length = DeviceInformation->DeviceName.Length + ReparseIndex.Length;
1481  ReparseFile.MaximumLength = ReparseFile.Length + sizeof(UNICODE_NULL);
1482  ReparseFile.Buffer = AllocatePool(ReparseFile.MaximumLength);
1483  if (!ReparseFile.Buffer)
1484  {
1485  return;
1486  }
1487 
1488  RtlCopyMemory(ReparseFile.Buffer, DeviceInformation->DeviceName.Buffer,
1489  DeviceInformation->DeviceName.Length);
1490  RtlCopyMemory((PVOID)((ULONG_PTR)ReparseFile.Buffer + DeviceInformation->DeviceName.Length),
1491  ReparseFile.Buffer, ReparseFile.Length);
1492  ReparseFile.Buffer[ReparseFile.Length / sizeof(WCHAR)] = UNICODE_NULL;
1493 
1495  &ReparseFile,
1497  NULL,
1498  NULL);
1499 
1500  /* Open reparse point */
1504  &IoStatusBlock,
1507  FreePool(ReparseFile.Buffer);
1508  if (!NT_SUCCESS(Status))
1509  {
1510  DeviceInformation->NoDatabase = FALSE;
1511  return;
1512  }
1513 
1514  /* Query reparse point information
1515  * We only pay attention to mout point
1516  */
1518  FileName.Buffer = FileNameBuffer;
1519  FileName.Length = sizeof(FileNameBuffer);
1520  FileName.MaximumLength = sizeof(FileNameBuffer);
1522  Status = ZwQueryDirectoryFile(Handle,
1523  NULL,
1524  NULL,
1525  NULL,
1526  &IoStatusBlock,
1527  &ReparsePointInformation,
1530  TRUE,
1531  &FileName,
1532  FALSE);
1533  if (!NT_SUCCESS(Status))
1534  {
1535  ZwClose(Handle);
1536  return;
1537  }
1538 
1539  RestartScan = TRUE;
1540 
1541  /* Query mount points */
1542  while (TRUE)
1543  {
1544  SymbolicName.Length = 0;
1545  SymbolicName.MaximumLength = sizeof(SymbolicNameBuffer);
1546  SymbolicName.Buffer = SymbolicNameBuffer;
1547  RtlCopyMemory(&SavedReparsePointInformation, &ReparsePointInformation, sizeof(FILE_REPARSE_POINT_INFORMATION));
1548 
1549  Status = ZwQueryDirectoryFile(Handle,
1550  NULL,
1551  NULL,
1552  NULL,
1553  &IoStatusBlock,
1554  &ReparsePointInformation,
1557  TRUE,
1558  (RestartScan) ? &FileName : NULL,
1559  RestartScan);
1560  if (!RestartScan)
1561  {
1562  if (ReparsePointInformation.FileReference == SavedReparsePointInformation.FileReference &&
1563  ReparsePointInformation.Tag == SavedReparsePointInformation.Tag)
1564  {
1565  break;
1566  }
1567  }
1568  else
1569  {
1570  RestartScan = FALSE;
1571  }
1572 
1573  if (!NT_SUCCESS(Status) || ReparsePointInformation.Tag != IO_REPARSE_TAG_MOUNT_POINT)
1574  {
1575  break;
1576  }
1577 
1578  /* Get the volume name associated to the mount point */
1580  &ReparsePointInformation,
1581  NULL, &SymbolicName,
1582  &VolumeName);
1583  if (!NT_SUCCESS(Status))
1584  {
1585  continue;
1586  }
1587 
1589 
1590  /* Get its information */
1591  Status = FindDeviceInfo(DeviceExtension, &SymbolicName,
1592  FALSE, &VolumeDeviceInformation);
1593  if (!NT_SUCCESS(Status))
1594  {
1595  DeviceInformation->NoDatabase = TRUE;
1596  continue;
1597  }
1598 
1599  /* If notification are enabled, mark it online */
1600  if (!DeviceInformation->SkipNotifications)
1601  {
1602  PostOnlineNotification(DeviceExtension, &VolumeDeviceInformation->SymbolicName);
1603  }
1604  }
1605 
1606  ZwClose(Handle);
1607 }
1608 
1609 /*
1610  * @implemented
1611  */
1612 VOID
1614  IN PDEVICE_INFORMATION DeviceInformation)
1615 {
1616  PRECONCILE_WORK_ITEM WorkItem;
1617 
1618  /* Removable devices don't have remote database */
1619  if (DeviceInformation->Removable)
1620  {
1621  return;
1622  }
1623 
1624  /* Allocate a work item */
1625  WorkItem = AllocatePool(sizeof(RECONCILE_WORK_ITEM));
1626  if (!WorkItem)
1627  {
1628  return;
1629  }
1630 
1631  WorkItem->WorkItem = IoAllocateWorkItem(DeviceExtension->DeviceObject);
1632  if (!WorkItem->WorkItem)
1633  {
1634  FreePool(WorkItem);
1635  return;
1636  }
1637 
1638  /* And queue it */
1640  WorkItem->DeviceExtension = DeviceExtension;
1641  WorkItem->DeviceInformation = DeviceInformation;
1642  QueueWorkItem(DeviceExtension, WorkItem, &(WorkItem->DeviceExtension));
1643 
1644  /* If there's no automount, and automatic letters
1645  * all volumes to find those online and notify there presence
1646  */
1647  if (DeviceExtension->WorkerThreadStatus == 0 &&
1648  DeviceExtension->AutomaticDriveLetter == 1 &&
1649  DeviceExtension->NoAutoMount == FALSE)
1650  {
1651  OnlineMountedVolumes(DeviceExtension, DeviceInformation);
1652  }
1653 }
1654 
1655 /*
1656  * @implemented
1657  */
1658 VOID
1660 {
1661  PLIST_ENTRY NextEntry;
1662  PDEVICE_INFORMATION DeviceInformation;
1663 
1664  /* Browse all the devices */
1665  for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1666  NextEntry != &(DeviceExtension->DeviceListHead);
1667  NextEntry = NextEntry->Flink)
1668  {
1669  DeviceInformation = CONTAINING_RECORD(NextEntry,
1671  DeviceListEntry);
1672  /* If it's not removable, then, it might have a database to sync */
1673  if (!DeviceInformation->Removable)
1674  {
1675  ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
1676  }
1677  }
1678 }
1679 
1680 /*
1681  * @implemented
1682  */
1683 VOID
1684 NTAPI
1686  IN PVOID Context)
1687 {
1688  NTSTATUS Status;
1689  HANDLE Database = 0;
1690  UNICODE_STRING DatabaseName;
1691  PMIGRATE_WORK_ITEM WorkItem;
1694  PDEVICE_INFORMATION DeviceInformation;
1695 
1697 
1698  /* Extract context */
1699  WorkItem = Context;
1700  DeviceInformation = WorkItem->DeviceInformation;
1701 
1702  /* Reconstruct appropriate string */
1703  DatabaseName.Length = DeviceInformation->DeviceName.Length + RemoteDatabase.Length;
1704  DatabaseName.MaximumLength = DatabaseName.Length + sizeof(WCHAR);
1705  DatabaseName.Buffer = AllocatePool(DatabaseName.MaximumLength);
1706  if (DatabaseName.Buffer == NULL)
1707  {
1709  goto Cleanup;
1710  }
1711 
1712  /* Create the required folder (in which the database will be stored
1713  * \System Volume Information at root of the volume
1714  */
1715  Status = RtlCreateSystemVolumeInformationFolder(&(DeviceInformation->DeviceName));
1716  if (!NT_SUCCESS(Status))
1717  {
1718  goto Cleanup;
1719  }
1720 
1721  /* Finish initiating strings */
1722  RtlCopyMemory(DatabaseName.Buffer, DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);
1723  RtlCopyMemory(DatabaseName.Buffer + (DeviceInformation->DeviceName.Length / sizeof(WCHAR)),
1725  DatabaseName.Buffer[DatabaseName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1726 
1727  /* Create database */
1729  &DatabaseName,
1731  NULL,
1732  NULL);
1733 
1739  &IoStatusBlock,
1740  NULL,
1742  0,
1743  FILE_CREATE,
1745  NULL,
1746  0,
1748  NULL,
1750  if (!NT_SUCCESS(Status))
1751  {
1753  {
1754  DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n");
1755  }
1756 
1757  Database = 0;
1758  goto Cleanup;
1759  }
1760 
1761 Cleanup:
1762  if (DatabaseName.Buffer)
1763  {
1764  FreePool(DatabaseName.Buffer);
1765  }
1766 
1767  if (NT_SUCCESS(Status))
1768  {
1769  DeviceInformation->Migrated = 1;
1770  }
1771  else if (Database != 0)
1772  {
1773  ZwClose(Database);
1774  }
1775 
1776  IoFreeWorkItem(WorkItem->WorkItem);
1777 
1778  WorkItem->WorkItem = NULL;
1779  WorkItem->Status = Status;
1780  WorkItem->Database = Database;
1781 
1782  KeSetEvent(WorkItem->Event, 0, FALSE);
1783 }
1784 
1785 /*
1786  * @implemented
1787  */
1788 NTSTATUS
1791 {
1792  KEVENT Event;
1793  NTSTATUS Status;
1794  PMIGRATE_WORK_ITEM WorkItem;
1795 
1797 
1798  /* Allocate a work item dedicated to migration */
1799  WorkItem = AllocatePool(sizeof(MIGRATE_WORK_ITEM));
1800  if (!WorkItem)
1801  {
1802  *Database = 0;
1804  }
1805 
1806  RtlZeroMemory(WorkItem, sizeof(MIGRATE_WORK_ITEM));
1807  WorkItem->Event = &Event;
1808  WorkItem->DeviceInformation = DeviceInformation;
1809  WorkItem->WorkItem = IoAllocateWorkItem(DeviceInformation->DeviceExtension->DeviceObject);
1810  if (!WorkItem->WorkItem)
1811  {
1812  FreePool(WorkItem);
1813  *Database = 0;
1815  }
1816 
1817  /* And queue it */
1818  IoQueueWorkItem(WorkItem->WorkItem,
1821  WorkItem);
1822 
1824  Status = WorkItem->Status;
1825 
1826  *Database = (NT_SUCCESS(Status) ? WorkItem->Database : 0);
1827 
1828  FreePool(WorkItem);
1829  return Status;
1830 }
1831 
1832 /*
1833  * @implemented
1834  */
1835 HANDLE
1837  IN BOOLEAN MigrateDatabase)
1838 {
1839  HANDLE Database;
1840  NTSTATUS Status;
1844  UNICODE_STRING DeviceRemoteDatabase;
1845 
1846  Database = 0;
1847 
1848  /* Get database name */
1849  DeviceRemoteDatabase.Length = DeviceInformation->DeviceName.Length + RemoteDatabase.Length;
1850  DeviceRemoteDatabase.MaximumLength = DeviceRemoteDatabase.Length + sizeof(WCHAR);
1851  DeviceRemoteDatabase.Buffer = AllocatePool(DeviceRemoteDatabase.MaximumLength);
1852  if (!DeviceRemoteDatabase.Buffer)
1853  {
1854  return 0;
1855  }
1856 
1857  RtlCopyMemory(DeviceRemoteDatabase.Buffer, DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);
1858  RtlCopyMemory(DeviceRemoteDatabase.Buffer + (DeviceInformation->DeviceName.Length / sizeof(WCHAR)),
1860  DeviceRemoteDatabase.Buffer[DeviceRemoteDatabase.Length / sizeof(WCHAR)] = UNICODE_NULL;
1861 
1862  /* Open database */
1864  &DeviceRemoteDatabase,
1866  NULL,
1867  NULL);
1868 
1869  /* Disable hard errors */
1871 
1877  &IoStatusBlock,
1878  NULL,
1880  0,
1881  (!MigrateDatabase || DeviceInformation->Migrated == 0) ? FILE_OPEN_IF : FILE_OPEN,
1883  NULL,
1884  0,
1886  NULL,
1889  {
1890  DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n");
1891  }
1892 
1893  /* If base it to be migrated and was opened successfully, go ahead */
1894  if (MigrateDatabase && NT_SUCCESS(Status))
1895  {
1896  CreateRemoteDatabase(DeviceInformation, &Database);
1897  }
1898 
1900  FreePool(DeviceRemoteDatabase.Buffer);
1901 
1902  return Database;
1903 }
1904 
1905 /*
1906  * @implemented
1907  */
1908 VOID
1910  IN PMOUNTDEV_UNIQUE_ID OldUniqueId,
1911  IN PMOUNTDEV_UNIQUE_ID NewUniqueId)
1912 {
1913  LONG Offset = 0;
1914  HANDLE Database;
1915  PDATABASE_ENTRY Entry, NewEntry;
1917 
1918  /* Open the remote database */
1919  Database = OpenRemoteDatabase(DeviceInformation, FALSE);
1920  if (!Database)
1921  {
1922  return;
1923  }
1924 
1925  /* Get all the entries */
1926  do
1927  {
1929  if (!Entry)
1930  {
1931  break;
1932  }
1933 
1934  /* Not the correct entry, skip it */
1935  if (Entry->UniqueIdLength != OldUniqueId->UniqueIdLength)
1936  {
1937  Offset += Entry->EntrySize;
1938  FreePool(Entry);
1939  continue;
1940  }
1941 
1942  /* Not the correct entry, skip it */
1943  if (RtlCompareMemory(OldUniqueId->UniqueId,
1944  (PVOID)((ULONG_PTR)Entry + Entry->UniqueIdOffset),
1945  Entry->UniqueIdLength) != Entry->UniqueIdLength)
1946  {
1947  Offset += Entry->EntrySize;
1948  FreePool(Entry);
1949  continue;
1950  }
1951 
1952  /* Here, we have the correct entry */
1953  NewEntry = AllocatePool(Entry->EntrySize + NewUniqueId->UniqueIdLength - OldUniqueId->UniqueIdLength);
1954  if (!NewEntry)
1955  {
1956  Offset += Entry->EntrySize;
1957  FreePool(Entry);
1958  continue;
1959  }
1960 
1961  /* Recreate the entry from the previous one */
1962  NewEntry->EntrySize = Entry->EntrySize + NewUniqueId->UniqueIdLength - OldUniqueId->UniqueIdLength;
1963  NewEntry->EntryReferences = Entry->EntryReferences;
1964  NewEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
1965  NewEntry->SymbolicNameLength = Entry->SymbolicNameLength;
1966  NewEntry->UniqueIdOffset = Entry->SymbolicNameLength + sizeof(DATABASE_ENTRY);
1967  NewEntry->UniqueIdLength = NewUniqueId->UniqueIdLength;
1968  RtlCopyMemory((PVOID)((ULONG_PTR)NewEntry + NewEntry->SymbolicNameOffset),
1969  (PVOID)((ULONG_PTR)Entry + Entry->SymbolicNameOffset),
1970  NewEntry->SymbolicNameLength);
1971  RtlCopyMemory((PVOID)((ULONG_PTR)NewEntry + NewEntry->UniqueIdOffset),
1972  NewUniqueId->UniqueId, NewEntry->UniqueIdLength);
1973 
1974  /* Delete old entry */
1976  if (!NT_SUCCESS(Status))
1977  {
1978  FreePool(Entry);
1979  FreePool(NewEntry);
1980  break;
1981  }
1982 
1983  /* And replace with new one */
1984  Status = AddRemoteDatabaseEntry(Database, NewEntry);
1985  FreePool(Entry);
1986  FreePool(NewEntry);
1987  } while (NT_SUCCESS(Status));
1988 
1990 
1991  return;
1992 }
1993 
1994 /*
1995  * @implemented
1996  */
1997 NTSTATUS
1998 NTAPI
2000  IN ULONG ValueType,
2001  IN PVOID ValueData,
2003  IN PVOID Context,
2005 {
2006  PMOUNTDEV_UNIQUE_ID UniqueId;
2007  UNICODE_STRING RegistryEntry;
2008 
2010 
2011  if (ValueType != REG_BINARY)
2012  {
2013  return STATUS_SUCCESS;
2014  }
2015 
2016  UniqueId = Context;
2017 
2018  /* First ensure we have the correct data */
2019  if (UniqueId->UniqueIdLength != ValueLength)
2020  {
2021  return STATUS_SUCCESS;
2022  }
2023 
2025  {
2026  return STATUS_SUCCESS;
2027  }
2028 
2029  RtlInitUnicodeString(&RegistryEntry, ValueName);
2030 
2031  /* Then, it's a drive letter, erase it */
2032  if (IsDriveLetter(&RegistryEntry))
2033  {
2035  DatabasePath,
2036  ValueName);
2037  }
2038 
2039  return STATUS_SUCCESS;
2040 }
2041 
2042 /*
2043  * @implemented
2044  */
2045 VOID
2047 {
2049 
2052 
2054  DatabasePath,
2055  QueryTable,
2056  UniqueId,
2057  NULL);
2058 }
2059 
2060 /*
2061  * @implemented
2062  */
2063 NTSTATUS
2064 NTAPI
2066  IN ULONG ValueType,
2067  IN PVOID ValueData,
2069  IN PVOID Context,
2071 {
2072  PMOUNTDEV_UNIQUE_ID UniqueId = Context;
2073 
2075 
2076  /* Ensure we have correct input */
2077  if (ValueName[0] != L'#' || ValueType != REG_BINARY ||
2078  UniqueId->UniqueIdLength != ValueLength)
2079  {
2080  return STATUS_SUCCESS;
2081  }
2082 
2083  /* And then, if unique ID matching, delete entry */
2085  {
2087  DatabasePath,
2088  ValueName);
2089  }
2090 
2091  return STATUS_SUCCESS;
2092 }
2093 
2094 /*
2095  * @implemented
2096  */
2097 VOID
2099 {
2101 
2104 
2106  DatabasePath,
2107  QueryTable,
2108  UniqueId,
2109  NULL);
2110 }
#define FILE_GENERIC_READ
Definition: nt_native.h:653
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
USHORT UniqueIdOffset
Definition: mntmgr.h:91
VOID DeleteRegistryDriveLetter(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:2046
#define FILE_WRITE_EA
Definition: nt_native.h:640
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4004
#define IN
Definition: typedefs.h:38
VOID NTAPI ReconcileThisDatabaseWithMasterWorker(IN PVOID Parameter)
Definition: database.c:560
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define LL
Definition: tui.h:85
NTSTATUS QueueWorkItem(IN PDEVICE_EXTENSION DeviceExtension, IN PRECONCILE_WORK_ITEM WorkItem, IN PVOID Context)
Definition: database.c:1261
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define FILE_OPEN_IF
Definition: from_kernel.h:56
VOID DeleteFromLocalDatabase(IN PUNICODE_STRING SymbolicLink, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:351
NTSTATUS DeleteRemoteDatabaseEntry(IN HANDLE Database, IN LONG StartingOffset)
Definition: database.c:233
NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR)
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN _In_ ULONG _In_opt_ PULONG _In_ BOOLEAN RestartScan
Definition: fltkernel.h:2298
WCHAR RootDirectory[MAX_PATH]
Definition: format.c:74
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
NTSTATUS TruncateRemoteDatabase(IN HANDLE Database, IN LONG NewSize)
Definition: database.c:91
struct _Entry Entry
Definition: kefuncs.h:640
NTSTATUS NTAPI QueryUniqueIdQueryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: database.c:401
ULONG EntryReferences
Definition: mntmgr.h:88
USHORT MaximumLength
Definition: env_spec_w32.h:370
ULONG EntrySize
Definition: mntmgr.h:87
#define REG_BINARY
Definition: nt_native.h:1496
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:54
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:98
_In_ PCWSTR _In_z_ PCWSTR _In_ ULONG ValueType
Definition: rtlfuncs.h:4016
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4676
LONG NTSTATUS
Definition: precomp.h:26
USHORT UniqueIdLength
Definition: imports.h:138
PKEVENT Event
Definition: mntmgr.h:134
#define FILE_CREATE
Definition: from_kernel.h:55
BOOLEAN IsUniqueIdPresent(IN PDEVICE_EXTENSION DeviceExtension, IN PDATABASE_ENTRY DatabaseEntry)
Definition: uniqueid.c:221
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:922
UNICODE_STRING RemoteDatabase
Definition: database.c:34
#define DO_UNLOAD_PENDING
Definition: env_spec_w32.h:392
NTSYSCALLAPI NTSTATUS NTAPI ZwOpenEvent(_Out_ PHANDLE EventHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
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 CreateRemoteDatabaseWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
Definition: database.c:1685
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
UNICODE_STRING SafeVolumes
Definition: symlink.c:38
NTSTATUS WriteUniqueIdToMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDATABASE_ENTRY DatabaseEntry)
Definition: database.c:489
uint16_t * PWCHAR
Definition: typedefs.h:54
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
_In_ PVOID Parameter
Definition: ldrtypes.h:241
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:97
#define InsertTailList(ListHead, Entry)
USHORT SymbolicNameLength
Definition: mntmgr.h:90
#define FILE_APPEND_DATA
Definition: nt_native.h:634
VOID DeleteNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:2098
NTSTATUS MountMgrCreatePointWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLinkName, IN PUNICODE_STRING DeviceName)
Definition: point.c:35
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
_In_ UCHAR EntrySize
Definition: iofuncs.h:640
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define FreePool(P)
Definition: mntmgr.h:154
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
UNICODE_STRING SymbolicName
Definition: mntmgr.h:48
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define STATUS_STOPPED_ON_SYMLINK
Definition: ntstatus.h:212
LIST_ENTRY AssociatedDevicesEntry
Definition: mntmgr.h:97
#define FILE_SHARE_READ
Definition: compat.h:125
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
LARGE_INTEGER AllocationSize
Definition: winternl.h:688
VOID OnlineMountedVolumes(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1460
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define IO_STOP_ON_SYMLINK
Definition: iotypes.h:6997
HANDLE Database
Definition: mntmgr.h:136
uint32_t ULONG_PTR
Definition: typedefs.h:63
NTSTATUS NTAPI DeleteFromLocalDatabaseRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: database.c:322
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:6875
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
UCHAR KIRQL
Definition: env_spec_w32.h:591
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
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
VOID ReconcileThisDatabaseWithMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1613
HANDLE OpenRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, IN BOOLEAN MigrateDatabase)
Definition: database.c:1836
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define UNICODE_NULL
long LONG
Definition: pedump.c:60
#define IO_NO_PARAMETER_CHECKING
Definition: iotypes.h:509
BOOLEAN NeedsReconcile
Definition: mntmgr.h:56
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define FILE_READ_DATA
Definition: nt_native.h:628
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:61
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:435
BOOLEAN NoDatabase
Definition: mntmgr.h:57
NTSYSAPI NTSTATUS NTAPI ZwFsControlFile(IN HANDLE DeviceHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, OUT PVOID OutputBuffer, IN ULONG OutputBufferSize)
unsigned char BOOLEAN
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4004
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
USHORT UniqueIdLength
Definition: mntmgr.h:92
NTSTATUS FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
Definition: mountmgr.c:642
void * PVOID
Definition: retypes.h:9
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
UNICODE_STRING ReparseIndex
Definition: symlink.c:40
#define InterlockedExchangeAdd
Definition: interlocked.h:181
#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
NTSTATUS CloseRemoteDatabase(IN HANDLE Database)
Definition: database.c:82
struct _DATABASE_ENTRY DATABASE_ENTRY
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE Handle
Definition: extypes.h:390
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
VOID ChangeRemoteDatabaseUniqueId(IN PDEVICE_INFORMATION DeviceInformation, IN PMOUNTDEV_UNIQUE_ID OldUniqueId, IN PMOUNTDEV_UNIQUE_ID NewUniqueId)
Definition: database.c:1909
BOOLEAN SkipNotifications
Definition: mntmgr.h:58
NTSTATUS NTAPI RtlCreateSystemVolumeInformationFolder(IN PUNICODE_STRING VolumeRootPath)
Definition: sysvol.c:545
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct _REPARSE_DATA_BUFFER::@308::@311 MountPointReparseBuffer
struct _RECONCILE_WORK_ITEM_CONTEXT * PRECONCILE_WORK_ITEM_CONTEXT
PDEVICE_INFORMATION DeviceInformation
Definition: mntmgr.h:133
PIO_WORKITEM WorkItem
Definition: mntmgr.h:132
VOID NTAPI WorkerThread(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
Definition: database.c:1148
Definition: mntmgr.h:95
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
NTSTATUS Status
Definition: mntmgr.h:135
USHORT SymbolicNameOffset
Definition: mntmgr.h:89
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
* PFILE_OBJECT
Definition: iotypes.h:1955
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define READ_CONTROL
Definition: nt_native.h:58
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
Definition: mntmgr.h:85
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
static const WCHAR L[]
Definition: oid.c:1250
#define InterlockedDecrement
Definition: armddk.h:52
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
BOOLEAN NTAPI IoSetThreadHardErrorMode(IN BOOLEAN HardErrorEnabled)
Definition: error.c:707
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
ULONG LowPart
Definition: typedefs.h:104
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
Definition: typedefs.h:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
static const WCHAR Cleanup[]
Definition: register.c:80
#define SYNCHRONIZE
Definition: nt_native.h:61
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
UNICODE_STRING String
Definition: mntmgr.h:99
#define AllocatePool(Size)
Definition: mntmgr.h:153
#define InterlockedExchange
Definition: armddk.h:54
PWSTR DatabasePath
Definition: database.c:31
Status
Definition: gdiplustypes.h:24
T MAX(T a, T b)
Definition: polytest.cpp:85
VOID PostOnlineNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName)
Definition: notify.c:145
#define FILE_OPEN
Definition: from_kernel.h:54
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
struct _FileName FileName
Definition: fatprocs.h:884
NTSTATUS NTAPI DeleteDriveLetterRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: database.c:1999
static ULONG Timeout
Definition: ping.c:61
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
NTSTATUS WriteRemoteDatabaseEntry(IN HANDLE Database, IN LONG Offset, IN PDATABASE_ENTRY Entry)
Definition: database.c:200
#define InterlockedIncrement
Definition: armddk.h:53
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
unsigned short USHORT
Definition: pedump.c:61
BOOLEAN Removable
Definition: mntmgr.h:54
NTSTATUS QueryVolumeName(IN HANDLE RootDirectory, IN PFILE_REPARSE_POINT_INFORMATION ReparsePointInformation, IN PUNICODE_STRING FileName OPTIONAL, OUT PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING VolumeName)
Definition: database.c:1292
#define FILE_READ_EA
Definition: nt_native.h:638
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
unsigned int * PULONG
Definition: retypes.h:1
VOID UpdateReplicatedUniqueIds(IN PDEVICE_INFORMATION DeviceInformation, IN PDATABASE_ENTRY DatabaseEntry)
Definition: uniqueid.c:376
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
NTSTATUS CreateRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, IN OUT PHANDLE Database)
Definition: database.c:1789
#define DPRINT1
Definition: precomp.h:8
#define FileStandardInformation
Definition: propsheet.cpp:61
UNICODE_STRING DeviceName
Definition: mntmgr.h:50
NTSTATUS NTAPI IoCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG Disposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength, IN CREATE_FILE_TYPE CreateFileType, IN PVOID ExtraCreateParameters OPTIONAL, IN ULONG Options)
Definition: file.c:3009
NTSTATUS WaitForRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:371
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
PIO_WORKITEM WorkItem
Definition: mntmgr.h:124
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
WCHAR FileNameBuffer[_MAX_PATH]
Definition: framewnd.c:239
PDATABASE_ENTRY GetRemoteDatabaseEntry(IN HANDLE Database, IN LONG StartingOffset)
Definition: database.c:125
#define OUT
Definition: typedefs.h:39
struct tagContext Context
Definition: acpixf.h:1030
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
LIST_ENTRY AssociatedDevicesHead
Definition: mntmgr.h:47
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSTATUS NTAPI DeleteNoDriveLetterEntryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: database.c:2065
NTSTATUS QueryUniqueIdFromMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, OUT PMOUNTDEV_UNIQUE_ID *UniqueId)
Definition: database.c:440
PWSTR OfflinePath
Definition: database.c:32
NTSTATUS AddRemoteDatabaseEntry(IN HANDLE Database, IN PDATABASE_ENTRY Entry)
Definition: database.c:64
VOID ReleaseRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:391
VOID ReconcileAllDatabasesWithMaster(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:1659
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE
Definition: iotypes.h:6857
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:49
PWORKER_THREAD_ROUTINE WorkerRoutine
Definition: mntmgr.h:125
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
UCHAR UniqueId[1]
Definition: imports.h:139
base of all file and directory entries
Definition: entries.h:82
static const WCHAR SymbolicLink[]
Definition: interface.c:31
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
LONGLONG QuadPart
Definition: typedefs.h:112
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716
LONG GetRemoteDatabaseSize(IN HANDLE Database)
Definition: database.c:40
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
KEVENT UnloadEvent
Definition: mountmgr.c:41
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68