ReactOS 0.4.16-dev-122-g325d74c
database.c File Reference
#include "mntmgr.h"
#include <debug.h>
Include dependency graph for database.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

LONG GetRemoteDatabaseSize (IN HANDLE Database)
 
NTSTATUS AddRemoteDatabaseEntry (IN HANDLE Database, IN PDATABASE_ENTRY Entry)
 
NTSTATUS CloseRemoteDatabase (IN HANDLE Database)
 
NTSTATUS TruncateRemoteDatabase (IN HANDLE Database, IN LONG NewSize)
 
PDATABASE_ENTRY GetRemoteDatabaseEntry (IN HANDLE Database, IN LONG StartingOffset)
 
NTSTATUS WriteRemoteDatabaseEntry (IN HANDLE Database, IN LONG Offset, IN PDATABASE_ENTRY Entry)
 
NTSTATUS DeleteRemoteDatabaseEntry (IN HANDLE Database, IN LONG StartingOffset)
 
NTSTATUS NTAPI DeleteFromLocalDatabaseRoutine (IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
 
VOID DeleteFromLocalDatabase (IN PUNICODE_STRING SymbolicLink, IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
NTSTATUS WaitForRemoteDatabaseSemaphore (IN PDEVICE_EXTENSION DeviceExtension)
 
VOID ReleaseRemoteDatabaseSemaphore (IN PDEVICE_EXTENSION DeviceExtension)
 
NTSTATUS NTAPI QueryUniqueIdQueryRoutine (IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
 
NTSTATUS QueryUniqueIdFromMaster (IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, OUT PMOUNTDEV_UNIQUE_ID *UniqueId)
 
NTSTATUS WriteUniqueIdToMaster (IN PDEVICE_EXTENSION DeviceExtension, IN PDATABASE_ENTRY DatabaseEntry)
 
VOID NTAPI ReconcileThisDatabaseWithMasterWorker (IN PVOID Parameter)
 
VOID NTAPI WorkerThread (IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
 
NTSTATUS QueueWorkItem (IN PDEVICE_EXTENSION DeviceExtension, IN PRECONCILE_WORK_ITEM WorkItem, IN PVOID Context)
 
NTSTATUS QueryVolumeName (IN HANDLE RootDirectory, IN PFILE_REPARSE_POINT_INFORMATION ReparsePointInformation, IN PUNICODE_STRING FileName OPTIONAL, OUT PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING VolumeName)
 
VOID OnlineMountedVolumes (IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
 
VOID ReconcileThisDatabaseWithMaster (IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
 
VOID ReconcileAllDatabasesWithMaster (IN PDEVICE_EXTENSION DeviceExtension)
 
VOID NTAPI CreateRemoteDatabaseWorker (IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
 
NTSTATUS CreateRemoteDatabase (IN PDEVICE_INFORMATION DeviceInformation, IN OUT PHANDLE Database)
 
HANDLE OpenRemoteDatabase (IN PDEVICE_INFORMATION DeviceInformation, IN BOOLEAN MigrateDatabase)
 
VOID ChangeRemoteDatabaseUniqueId (IN PDEVICE_INFORMATION DeviceInformation, IN PMOUNTDEV_UNIQUE_ID OldUniqueId, IN PMOUNTDEV_UNIQUE_ID NewUniqueId)
 
NTSTATUS NTAPI DeleteDriveLetterRoutine (IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
 
VOID DeleteRegistryDriveLetter (IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
NTSTATUS NTAPI DeleteNoDriveLetterEntryRoutine (IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
 
VOID DeleteNoDriveLetterEntry (IN PMOUNTDEV_UNIQUE_ID UniqueId)
 

Variables

PWSTR DatabasePath = L"\\Registry\\Machine\\System\\MountedDevices"
 
PWSTR OfflinePath = L"\\Registry\\Machine\\System\\MountedDevices\\Offline"
 
UNICODE_STRING RemoteDatabase = RTL_CONSTANT_STRING(L"\\System Volume Information\\MountPointManagerRemoteDatabase")
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 28 of file database.c.

Function Documentation

◆ AddRemoteDatabaseEntry()

NTSTATUS AddRemoteDatabaseEntry ( IN HANDLE  Database,
IN PDATABASE_ENTRY  Entry 
)

Definition at line 64 of file database.c.

66{
69
70 /* Get size to append data */
72
73 return ZwWriteFile(Database, NULL, NULL, NULL,
75 Entry->EntrySize, &Size, NULL);
76}
#define NULL
Definition: types.h:112
LONG GetRemoteDatabaseSize(IN HANDLE Database)
Definition: database.c:40
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
base of all file and directory entries
Definition: entries.h:83
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by ChangeRemoteDatabaseUniqueId(), MountMgrVolumeMountPointCreated(), and ReconcileThisDatabaseWithMasterWorker().

◆ ChangeRemoteDatabaseUniqueId()

VOID ChangeRemoteDatabaseUniqueId ( IN PDEVICE_INFORMATION  DeviceInformation,
IN PMOUNTDEV_UNIQUE_ID  OldUniqueId,
IN PMOUNTDEV_UNIQUE_ID  NewUniqueId 
)

Definition at line 1911 of file database.c.

1914{
1915 LONG Offset = 0;
1917 PDATABASE_ENTRY Entry, NewEntry;
1919
1920 /* Open the remote database */
1921 Database = OpenRemoteDatabase(DeviceInformation, FALSE);
1922 if (!Database)
1923 {
1924 return;
1925 }
1926
1927 /* Get all the entries */
1928 do
1929 {
1931 if (!Entry)
1932 {
1933 break;
1934 }
1935
1936 /* Not the correct entry, skip it */
1937 if (Entry->UniqueIdLength != OldUniqueId->UniqueIdLength)
1938 {
1939 Offset += Entry->EntrySize;
1940 FreePool(Entry);
1941 continue;
1942 }
1943
1944 /* Not the correct entry, skip it */
1945 if (RtlCompareMemory(OldUniqueId->UniqueId,
1946 (PVOID)((ULONG_PTR)Entry + Entry->UniqueIdOffset),
1947 Entry->UniqueIdLength) != Entry->UniqueIdLength)
1948 {
1949 Offset += Entry->EntrySize;
1950 FreePool(Entry);
1951 continue;
1952 }
1953
1954 /* Here, we have the correct entry */
1955 NewEntry = AllocatePool(Entry->EntrySize + NewUniqueId->UniqueIdLength - OldUniqueId->UniqueIdLength);
1956 if (!NewEntry)
1957 {
1958 Offset += Entry->EntrySize;
1959 FreePool(Entry);
1960 continue;
1961 }
1962
1963 /* Recreate the entry from the previous one */
1964 NewEntry->EntrySize = Entry->EntrySize + NewUniqueId->UniqueIdLength - OldUniqueId->UniqueIdLength;
1965 NewEntry->EntryReferences = Entry->EntryReferences;
1966 NewEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
1967 NewEntry->SymbolicNameLength = Entry->SymbolicNameLength;
1968 NewEntry->UniqueIdOffset = Entry->SymbolicNameLength + sizeof(DATABASE_ENTRY);
1969 NewEntry->UniqueIdLength = NewUniqueId->UniqueIdLength;
1970 RtlCopyMemory((PVOID)((ULONG_PTR)NewEntry + NewEntry->SymbolicNameOffset),
1971 (PVOID)((ULONG_PTR)Entry + Entry->SymbolicNameOffset),
1972 NewEntry->SymbolicNameLength);
1973 RtlCopyMemory((PVOID)((ULONG_PTR)NewEntry + NewEntry->UniqueIdOffset),
1974 NewUniqueId->UniqueId, NewEntry->UniqueIdLength);
1975
1976 /* Delete old entry */
1978 if (!NT_SUCCESS(Status))
1979 {
1980 FreePool(Entry);
1981 FreePool(NewEntry);
1982 break;
1983 }
1984
1985 /* And replace with new one */
1987 FreePool(Entry);
1988 FreePool(NewEntry);
1989 } while (NT_SUCCESS(Status));
1990
1992
1993 return;
1994}
LONG NTSTATUS
Definition: precomp.h:26
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
NTSTATUS CloseRemoteDatabase(IN HANDLE Database)
Definition: database.c:82
NTSTATUS DeleteRemoteDatabaseEntry(IN HANDLE Database, IN LONG StartingOffset)
Definition: database.c:233
NTSTATUS AddRemoteDatabaseEntry(IN HANDLE Database, IN PDATABASE_ENTRY Entry)
Definition: database.c:64
HANDLE OpenRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, IN BOOLEAN MigrateDatabase)
Definition: database.c:1837
PDATABASE_ENTRY GetRemoteDatabaseEntry(IN HANDLE Database, IN LONG StartingOffset)
Definition: database.c:125
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
Status
Definition: gdiplustypes.h:25
struct _DATABASE_ENTRY DATABASE_ENTRY
#define AllocatePool(Size)
Definition: mntmgr.h:153
#define FreePool(P)
Definition: mntmgr.h:154
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
long LONG
Definition: pedump.c:60
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: mntmgr.h:86
USHORT UniqueIdOffset
Definition: mntmgr.h:91
USHORT SymbolicNameLength
Definition: mntmgr.h:90
USHORT UniqueIdLength
Definition: mntmgr.h:92
ULONG EntrySize
Definition: mntmgr.h:87
ULONG EntryReferences
Definition: mntmgr.h:88
USHORT SymbolicNameOffset
Definition: mntmgr.h:89
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by MountMgrUniqueIdChangeRoutine().

◆ CloseRemoteDatabase()

NTSTATUS CloseRemoteDatabase ( IN HANDLE  Database)

Definition at line 82 of file database.c.

83{
84 return ZwClose(Database);
85}
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)

Referenced by ChangeRemoteDatabaseUniqueId(), MountMgrVolumeMountPointCreated(), MountMgrVolumeMountPointDeleted(), and ReconcileThisDatabaseWithMasterWorker().

◆ CreateRemoteDatabase()

NTSTATUS CreateRemoteDatabase ( IN PDEVICE_INFORMATION  DeviceInformation,
IN OUT PHANDLE  Database 
)

Definition at line 1790 of file database.c.

1792{
1793 KEVENT Event;
1796
1798
1799 /* Allocate a work item dedicated to migration */
1801 if (!WorkItem)
1802 {
1803 *Database = 0;
1805 }
1806
1808 WorkItem->Event = &Event;
1809 WorkItem->DeviceInformation = DeviceInformation;
1810 WorkItem->WorkItem = IoAllocateWorkItem(DeviceInformation->DeviceExtension->DeviceObject);
1811 if (!WorkItem->WorkItem)
1812 {
1814 *Database = 0;
1816 }
1817
1818 /* And queue it */
1819 IoQueueWorkItem(WorkItem->WorkItem,
1822 WorkItem);
1823
1825 Status = WorkItem->Status;
1826
1827 *Database = (NT_SUCCESS(Status) ? WorkItem->Database : 0);
1828
1830 return Status;
1831}
VOID NTAPI CreateRemoteDatabaseWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
Definition: database.c:1685
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
#define KernelMode
Definition: asm.h:34
@ NotificationEvent
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
@ DelayedWorkQueue
Definition: extypes.h:190
@ Executive
Definition: ketypes.h:415

Referenced by OpenRemoteDatabase().

◆ CreateRemoteDatabaseWorker()

VOID NTAPI CreateRemoteDatabaseWorker ( IN PDEVICE_OBJECT  DeviceObject,
IN PVOID  Context 
)

Definition at line 1685 of file database.c.

1687{
1689 HANDLE Database = 0;
1690 UNICODE_STRING DatabaseName;
1694 PDEVICE_INFORMATION DeviceInformation;
1695
1697
1698 /* Extract context */
1699 WorkItem = Context;
1700 DeviceInformation = WorkItem->DeviceInformation;
1701
1702 /* Reconstruct appropriate string */
1703 DatabaseName.Length = 0;
1704 DatabaseName.MaximumLength = DeviceInformation->DeviceName.Length
1706 + sizeof(UNICODE_NULL);
1707 DatabaseName.Buffer = AllocatePool(DatabaseName.MaximumLength);
1708 if (DatabaseName.Buffer == NULL)
1709 {
1711 goto Cleanup;
1712 }
1713
1714 /* Create the required folder (in which the database will be stored
1715 * \System Volume Information at root of the volume
1716 */
1718 if (!NT_SUCCESS(Status))
1719 {
1720 goto Cleanup;
1721 }
1722
1723 /* Finish initiating strings */
1724 RtlAppendUnicodeStringToString(&DatabaseName, &DeviceInformation->DeviceName);
1726 DatabaseName.Buffer[DatabaseName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1727
1728 /* Create database */
1730 &DatabaseName,
1732 NULL,
1733 NULL);
1734
1741 NULL,
1743 0,
1746 NULL,
1747 0,
1749 NULL,
1751 if (!NT_SUCCESS(Status))
1752 {
1754 {
1755 DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n");
1756 }
1757
1758 Database = 0;
1759 goto Cleanup;
1760 }
1761
1762Cleanup:
1763 if (DatabaseName.Buffer)
1764 {
1765 FreePool(DatabaseName.Buffer);
1766 }
1767
1768 if (NT_SUCCESS(Status))
1769 {
1770 DeviceInformation->Migrated = 1;
1771 }
1772 else if (Database != 0)
1773 {
1775 }
1776
1777 IoFreeWorkItem(WorkItem->WorkItem);
1778
1779 WorkItem->WorkItem = NULL;
1780 WorkItem->Status = Status;
1781 WorkItem->Database = Database;
1782
1783 KeSetEvent(WorkItem->Event, 0, FALSE);
1784}
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define DPRINT1
Definition: precomp.h:8
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
static const WCHAR Cleanup[]
Definition: register.c:80
UNICODE_STRING RemoteDatabase
Definition: database.c:34
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define FILE_CREATE
Definition: from_kernel.h:55
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define FILE_READ_EA
Definition: nt_native.h:638
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_APPEND_DATA
Definition: nt_native.h:634
#define READ_CONTROL
Definition: nt_native.h:58
#define FILE_WRITE_EA
Definition: nt_native.h:640
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
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:3010
#define STATUS_STOPPED_ON_SYMLINK
Definition: ntstatus.h:224
UNICODE_STRING DeviceName
Definition: mntmgr.h:50
USHORT MaximumLength
Definition: env_spec_w32.h:370
NTSTATUS NTAPI RtlCreateSystemVolumeInformationFolder(IN PUNICODE_STRING VolumeRootPath)
Definition: sysvol.c:551
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define IO_NO_PARAMETER_CHECKING
Definition: iotypes.h:541
@ CreateFileTypeNone
Definition: iotypes.h:535
#define IO_STOP_ON_SYMLINK
Definition: iotypes.h:7353
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by CreateRemoteDatabase().

◆ DeleteDriveLetterRoutine()

NTSTATUS NTAPI DeleteDriveLetterRoutine ( IN PWSTR  ValueName,
IN ULONG  ValueType,
IN PVOID  ValueData,
IN ULONG  ValueLength,
IN PVOID  Context,
IN PVOID  EntryContext 
)

Definition at line 2001 of file database.c.

2007{
2008 PMOUNTDEV_UNIQUE_ID UniqueId;
2009 UNICODE_STRING RegistryEntry;
2010
2012
2013 if (ValueType != REG_BINARY)
2014 {
2015 return STATUS_SUCCESS;
2016 }
2017
2018 UniqueId = Context;
2019
2020 /* First ensure we have the correct data */
2021 if (UniqueId->UniqueIdLength != ValueLength)
2022 {
2023 return STATUS_SUCCESS;
2024 }
2025
2027 {
2028 return STATUS_SUCCESS;
2029 }
2030
2031 RtlInitUnicodeString(&RegistryEntry, ValueName);
2032
2033 /* Then, it's a drive letter, erase it */
2034 if (IsDriveLetter(&RegistryEntry))
2035 {
2038 ValueName);
2039 }
2040
2041 return STATUS_SUCCESS;
2042}
PWSTR DatabasePath
Definition: database.c:31
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR)
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:812
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4219
#define REG_BINARY
Definition: nt_native.h:1496
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
USHORT UniqueIdLength
Definition: imports.h:136
UCHAR UniqueId[1]
Definition: imports.h:137
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275

Referenced by DeleteRegistryDriveLetter().

◆ DeleteFromLocalDatabase()

VOID DeleteFromLocalDatabase ( IN PUNICODE_STRING  SymbolicLink,
IN PMOUNTDEV_UNIQUE_ID  UniqueId 
)

Definition at line 351 of file database.c.

353{
355
358 QueryTable[0].Name = SymbolicLink->Buffer;
359
363 UniqueId,
364 NULL);
365}
static const WCHAR SymbolicLink[]
Definition: interface.c:31
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
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4220
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109

Referenced by MountMgrMountedDeviceArrival().

◆ DeleteFromLocalDatabaseRoutine()

NTSTATUS NTAPI DeleteFromLocalDatabaseRoutine ( IN PWSTR  ValueName,
IN ULONG  ValueType,
IN PVOID  ValueData,
IN ULONG  ValueLength,
IN PVOID  Context,
IN PVOID  EntryContext 
)

Definition at line 322 of file database.c.

328{
329 PMOUNTDEV_UNIQUE_ID UniqueId = Context;
330
333
334 /* Ensure it matches, and delete */
335 if ((UniqueId->UniqueIdLength == ValueLength) &&
338 {
341 ValueName);
342 }
343
344 return STATUS_SUCCESS;
345}

Referenced by DeleteFromLocalDatabase().

◆ DeleteNoDriveLetterEntry()

VOID DeleteNoDriveLetterEntry ( IN PMOUNTDEV_UNIQUE_ID  UniqueId)

Definition at line 2100 of file database.c.

2101{
2103
2106
2109 QueryTable,
2110 UniqueId,
2111 NULL);
2112}
NTSTATUS NTAPI DeleteNoDriveLetterEntryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: database.c:2067

Referenced by MountMgrCreatePointWorker(), and MountMgrDeletePoints().

◆ DeleteNoDriveLetterEntryRoutine()

NTSTATUS NTAPI DeleteNoDriveLetterEntryRoutine ( IN PWSTR  ValueName,
IN ULONG  ValueType,
IN PVOID  ValueData,
IN ULONG  ValueLength,
IN PVOID  Context,
IN PVOID  EntryContext 
)

Definition at line 2067 of file database.c.

2073{
2074 PMOUNTDEV_UNIQUE_ID UniqueId = Context;
2075
2077
2078 /* Ensure we have correct input */
2079 if (ValueName[0] != L'#' || ValueType != REG_BINARY ||
2080 UniqueId->UniqueIdLength != ValueLength)
2081 {
2082 return STATUS_SUCCESS;
2083 }
2084
2085 /* And then, if unique ID matching, delete entry */
2087 {
2090 ValueName);
2091 }
2092
2093 return STATUS_SUCCESS;
2094}
#define L(x)
Definition: ntvdm.h:50

Referenced by DeleteNoDriveLetterEntry().

◆ DeleteRegistryDriveLetter()

VOID DeleteRegistryDriveLetter ( IN PMOUNTDEV_UNIQUE_ID  UniqueId)

Definition at line 2048 of file database.c.

2049{
2051
2054
2057 QueryTable,
2058 UniqueId,
2059 NULL);
2060}
NTSTATUS NTAPI DeleteDriveLetterRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: database.c:2001

Referenced by MountMgrCreatePointWorker().

◆ DeleteRemoteDatabaseEntry()

NTSTATUS DeleteRemoteDatabaseEntry ( IN HANDLE  Database,
IN LONG  StartingOffset 
)

Definition at line 233 of file database.c.

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 */
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 {
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 */
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}
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
NTSTATUS TruncateRemoteDatabase(IN HANDLE Database, IN LONG NewSize)
Definition: database.c:91
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONGLONG QuadPart
Definition: typedefs.h:114

Referenced by ChangeRemoteDatabaseUniqueId(), MountMgrVolumeMountPointDeleted(), and ReconcileThisDatabaseWithMasterWorker().

◆ GetRemoteDatabaseEntry()

PDATABASE_ENTRY GetRemoteDatabaseEntry ( IN HANDLE  Database,
IN LONG  StartingOffset 
)

Definition at line 125 of file database.c.

127{
133
134 /* Get the entry at the given position */
135 ByteOffset.QuadPart = StartingOffset;
136 Status = ZwReadFile(Database,
137 NULL,
138 NULL,
139 NULL,
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,
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 {
181 return NULL;
182 }
183
184 /* Validate entry */
185 if (MAX(Entry->SymbolicNameOffset + Entry->SymbolicNameLength,
186 Entry->UniqueIdOffset + Entry->UniqueIdLength) > (LONG)EntrySize)
187 {
190 return NULL;
191 }
192
193 return Entry;
194}
#define MAX(x, y)
Definition: rdesktop.h:175
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:732
_In_ UCHAR EntrySize
Definition: iofuncs.h:642

Referenced by ChangeRemoteDatabaseUniqueId(), DeleteRemoteDatabaseEntry(), MountMgrVolumeMountPointCreated(), MountMgrVolumeMountPointDeleted(), and ReconcileThisDatabaseWithMasterWorker().

◆ GetRemoteDatabaseSize()

LONG GetRemoteDatabaseSize ( IN HANDLE  Database)

Definition at line 40 of file database.c.

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}
#define FileStandardInformation
Definition: propsheet.cpp:61
ULONG LowPart
Definition: typedefs.h:106

Referenced by AddRemoteDatabaseEntry(), and DeleteRemoteDatabaseEntry().

◆ OnlineMountedVolumes()

VOID OnlineMountedVolumes ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PDEVICE_INFORMATION  DeviceInformation 
)

Definition at line 1460 of file database.c.

1462{
1463 HANDLE Handle;
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 = 0;
1481 ReparseFile.MaximumLength = DeviceInformation->DeviceName.Length
1483 + sizeof(UNICODE_NULL);
1484 ReparseFile.Buffer = AllocatePool(ReparseFile.MaximumLength);
1485 if (!ReparseFile.Buffer)
1486 {
1487 return;
1488 }
1489
1490 RtlAppendUnicodeStringToString(&ReparseFile, &DeviceInformation->DeviceName);
1492 ReparseFile.Buffer[ReparseFile.Length / sizeof(WCHAR)] = UNICODE_NULL;
1493
1495 &ReparseFile,
1497 NULL,
1498 NULL);
1499
1500 /* Open reparse point */
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,
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,
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 {
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,
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}
unsigned char BOOLEAN
WCHAR FileNameBuffer[MAX_PATH]
Definition: framewnd.c:225
#define TRUE
Definition: types.h:120
#define FILE_SHARE_READ
Definition: compat.h:136
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
struct _FileName FileName
Definition: fatprocs.h:897
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN _In_ ULONG _In_opt_ PULONG _In_ BOOLEAN RestartScan
Definition: fltkernel.h:2299
@ FileReparsePointInformation
Definition: from_kernel.h:94
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
ULONG Handle
Definition: gdb_input.c:15
UNICODE_STRING ReparseIndex
Definition: symlink.c:49
NTSTATUS FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
Definition: mountmgr.c:561
VOID PostOnlineNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName)
Definition: notify.c:122
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4677
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_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_GENERIC_READ
Definition: nt_native.h:653
UNICODE_STRING SymbolicName
Definition: mntmgr.h:48
uint32_t * PULONG
Definition: typedefs.h:59
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231

Referenced by ReconcileThisDatabaseWithMaster().

◆ OpenRemoteDatabase()

HANDLE OpenRemoteDatabase ( IN PDEVICE_INFORMATION  DeviceInformation,
IN BOOLEAN  MigrateDatabase 
)

Definition at line 1837 of file database.c.

1839{
1845 UNICODE_STRING DeviceRemoteDatabase;
1846
1847 Database = 0;
1848
1849 /* Get database name */
1850 DeviceRemoteDatabase.Length = 0;
1851 DeviceRemoteDatabase.MaximumLength = DeviceInformation->DeviceName.Length
1853 + sizeof(UNICODE_NULL);
1854 DeviceRemoteDatabase.Buffer = AllocatePool(DeviceRemoteDatabase.MaximumLength);
1855 if (!DeviceRemoteDatabase.Buffer)
1856 {
1857 return 0;
1858 }
1859
1860 RtlAppendUnicodeStringToString(&DeviceRemoteDatabase, &DeviceInformation->DeviceName);
1861 RtlAppendUnicodeStringToString(&DeviceRemoteDatabase, &RemoteDatabase);
1862 DeviceRemoteDatabase.Buffer[DeviceRemoteDatabase.Length / sizeof(WCHAR)] = UNICODE_NULL;
1863
1864 /* Open database */
1866 &DeviceRemoteDatabase,
1868 NULL,
1869 NULL);
1870
1871 /* Disable hard errors */
1873
1880 NULL,
1882 0,
1883 (!MigrateDatabase || DeviceInformation->Migrated == 0) ? FILE_OPEN_IF : FILE_OPEN,
1885 NULL,
1886 0,
1888 NULL,
1891 {
1892 DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n");
1893 }
1894
1895 /* If base it to be migrated and was opened successfully, go ahead */
1896 if (MigrateDatabase && NT_SUCCESS(Status))
1897 {
1898 CreateRemoteDatabase(DeviceInformation, &Database);
1899 }
1900
1902 FreePool(DeviceRemoteDatabase.Buffer);
1903
1904 return Database;
1905}
NTSTATUS CreateRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, IN OUT PHANDLE Database)
Definition: database.c:1790
#define FILE_OPEN
Definition: from_kernel.h:54
#define FILE_OPEN_IF
Definition: from_kernel.h:56
BOOLEAN NTAPI IoSetThreadHardErrorMode(IN BOOLEAN HardErrorEnabled)
Definition: error.c:726
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103

Referenced by ChangeRemoteDatabaseUniqueId(), MountMgrVolumeMountPointCreated(), MountMgrVolumeMountPointDeleted(), and ReconcileThisDatabaseWithMasterWorker().

◆ QueryUniqueIdFromMaster()

NTSTATUS QueryUniqueIdFromMaster ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PUNICODE_STRING  SymbolicName,
OUT PMOUNTDEV_UNIQUE_ID UniqueId 
)

Definition at line 440 of file database.c.

443{
445 PDEVICE_INFORMATION DeviceInformation;
447
448 /* Query the unique ID */
452
453 *UniqueId = NULL;
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}
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
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:49

Referenced by ReconcileThisDatabaseWithMasterWorker().

◆ QueryUniqueIdQueryRoutine()

NTSTATUS NTAPI QueryUniqueIdQueryRoutine ( IN PWSTR  ValueName,
IN ULONG  ValueType,
IN PVOID  ValueData,
IN ULONG  ValueLength,
IN PVOID  Context,
IN PVOID  EntryContext 
)

Definition at line 401 of file database.c.

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}
unsigned short USHORT
Definition: pedump.c:61

Referenced by QueryUniqueIdFromMaster().

◆ QueryVolumeName()

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 at line 1292 of file database.c.

1297{
1298 HANDLE Handle;
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,
1314 NULL);
1315 }
1316 else
1317 {
1319 FileName,
1321 NULL,
1322 NULL);
1323 }
1324
1325 /* Open volume */
1333 if (!NT_SUCCESS(Status))
1334 {
1335 return Status;
1336 }
1337
1338 /* Get the reparse point data */
1340 if (!ReparseDataBuffer)
1341 {
1342 ZwClose(Handle);
1344 }
1345
1347 0,
1348 NULL,
1349 NULL,
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);
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);
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);
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,
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,
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}
WCHAR RootDirectory[MAX_PATH]
Definition: format.c:74
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
@ FileNameInformation
Definition: from_kernel.h:70
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:81
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
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)
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:746
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
struct _REPARSE_DATA_BUFFER::@312::@315 MountPointReparseBuffer
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE
Definition: iotypes.h:7213

Referenced by MountMgrVolumeMountPointCreated(), MountMgrVolumeMountPointDeleted(), OnlineMountedVolumes(), and ReconcileThisDatabaseWithMasterWorker().

◆ QueueWorkItem()

NTSTATUS QueueWorkItem ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PRECONCILE_WORK_ITEM  WorkItem,
IN PVOID  Context 
)

Definition at line 1261 of file database.c.

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}
#define InterlockedIncrement
Definition: armddk.h:53
VOID NTAPI WorkerThread(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
Definition: database.c:1148
#define InsertTailList(ListHead, Entry)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by ReconcileThisDatabaseWithMaster().

◆ ReconcileAllDatabasesWithMaster()

VOID ReconcileAllDatabasesWithMaster ( IN PDEVICE_EXTENSION  DeviceExtension)

Definition at line 1659 of file database.c.

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}
VOID ReconcileThisDatabaseWithMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1613
BOOLEAN Removable
Definition: mntmgr.h:54
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by MountMgrDeviceControl().

◆ ReconcileThisDatabaseWithMaster()

VOID ReconcileThisDatabaseWithMaster ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PDEVICE_INFORMATION  DeviceInformation 
)

Definition at line 1613 of file database.c.

1615{
1617
1618 /* Removable devices don't have remote database */
1619 if (DeviceInformation->Removable)
1620 {
1621 return;
1622 }
1623
1624 /* Allocate a work item */
1626 if (!WorkItem)
1627 {
1628 return;
1629 }
1630
1631 WorkItem->WorkItem = IoAllocateWorkItem(DeviceExtension->DeviceObject);
1632 if (!WorkItem->WorkItem)
1633 {
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 the worker thread isn't started yet, automatic drive letter is
1645 * enabled but automount disabled, manually set mounted volumes online.
1646 * Otherwise, they will be set online during database reconciliation. */
1647 if (DeviceExtension->WorkerThreadStatus == 0 &&
1648 DeviceExtension->AutomaticDriveLetter &&
1649 DeviceExtension->NoAutoMount)
1650 {
1651 OnlineMountedVolumes(DeviceExtension, DeviceInformation);
1652 }
1653}
VOID OnlineMountedVolumes(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1460
VOID NTAPI ReconcileThisDatabaseWithMasterWorker(IN PVOID Parameter)
Definition: database.c:560
NTSTATUS QueueWorkItem(IN PDEVICE_EXTENSION DeviceExtension, IN PRECONCILE_WORK_ITEM WorkItem, IN PVOID Context)
Definition: database.c:1261

Referenced by MountMgrCreatePointWorker(), MountMgrMountedDeviceArrival(), MountMgrTargetDeviceNotification(), MountMgrUniqueIdChangeRoutine(), MountMgrVolumeMountPointChanged(), and ReconcileAllDatabasesWithMaster().

◆ ReconcileThisDatabaseWithMasterWorker()

VOID NTAPI ReconcileThisDatabaseWithMasterWorker ( IN PVOID  Parameter)

Definition at line 560 of file database.c.

561{
566 PMOUNTDEV_UNIQUE_ID UniqueId;
567 PDATABASE_ENTRY DatabaseEntry;
568 HANDLE DatabaseHandle, Handle;
571 PDEVICE_INFORMATION ListDeviceInfo;
572 PLIST_ENTRY Entry, EntryInfo, NextEntry;
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 */
628 if (!(DeviceObject->Flags & DO_UNLOAD_PENDING))
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);
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 = 0;
669 ReparseFile.MaximumLength = DeviceInformation->DeviceName.Length
671 + sizeof(UNICODE_NULL);
672 ReparseFile.Buffer = AllocatePool(ReparseFile.MaximumLength);
673 if (!ReparseFile.Buffer)
674 {
675 if (DatabaseHandle != 0)
676 {
677 CloseRemoteDatabase(DatabaseHandle);
678 }
679 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
680 goto ReleaseRDS;
681 }
682
683 RtlAppendUnicodeStringToString(&ReparseFile, &DeviceInformation->DeviceName);
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);
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,
729 &ReparsePointInformation,
732 TRUE,
733 &FileName,
734 FALSE);
735 if (!NT_SUCCESS(Status))
736 {
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);
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,
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! */
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 */
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
1126FreeUniqueId:
1127 FreePool(UniqueId);
1128ReleaseDeviceLock:
1129 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1130FreeDBEntry:
1131 FreePool(DatabaseEntry);
1132FreeVolume:
1134CloseReparse:
1135 ZwClose(Handle);
1136CloseRDB:
1137 CloseRemoteDatabase(DatabaseHandle);
1138ReleaseRDS:
1139 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
1140 return;
1141}
NTSTATUS QueryUniqueIdFromMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, OUT PMOUNTDEV_UNIQUE_ID *UniqueId)
Definition: database.c:440
NTSTATUS WaitForRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:371
VOID ReleaseRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:391
NTSTATUS WriteUniqueIdToMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDATABASE_ENTRY DatabaseEntry)
Definition: database.c:489
NTSTATUS WriteRemoteDatabaseEntry(IN HANDLE Database, IN LONG Offset, IN PDATABASE_ENTRY Entry)
Definition: database.c:200
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define DO_UNLOAD_PENDING
Definition: env_spec_w32.h:392
@ Unloading
Definition: fs_rec.h:188
#define InterlockedExchangeAdd
Definition: interlocked.h:181
struct _RECONCILE_WORK_ITEM_CONTEXT * PRECONCILE_WORK_ITEM_CONTEXT
VOID UpdateReplicatedUniqueIds(IN PDEVICE_INFORMATION DeviceInformation, IN PDATABASE_ENTRY DatabaseEntry)
Definition: uniqueid.c:376
BOOLEAN IsUniqueIdPresent(IN PDEVICE_EXTENSION DeviceExtension, IN PDATABASE_ENTRY DatabaseEntry)
Definition: uniqueid.c:221
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
@ Restart
Definition: sacdrv.h:269
Definition: mntmgr.h:96
BOOLEAN NoDatabase
Definition: mntmgr.h:57
BOOLEAN SkipNotifications
Definition: mntmgr.h:58
BOOLEAN NeedsReconcile
Definition: mntmgr.h:56
LIST_ENTRY AssociatedDevicesHead
Definition: mntmgr.h:47
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_In_ WDFDEVICE AssociatedDevice
Definition: wdfinterrupt.h:173
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336

Referenced by MountMgrQueryDosVolumePaths(), and ReconcileThisDatabaseWithMaster().

◆ ReleaseRemoteDatabaseSemaphore()

VOID ReleaseRemoteDatabaseSemaphore ( IN PDEVICE_EXTENSION  DeviceExtension)

Definition at line 391 of file database.c.

392{
393 KeReleaseSemaphore(&(DeviceExtension->RemoteDatabaseLock), IO_NO_INCREMENT, 1, FALSE);
394}

Referenced by MountMgrDeviceControl(), MountMgrUniqueIdChangeRoutine(), and ReconcileThisDatabaseWithMasterWorker().

◆ TruncateRemoteDatabase()

NTSTATUS TruncateRemoteDatabase ( IN HANDLE  Database,
IN LONG  NewSize 
)

Definition at line 91 of file database.c.

93{
98
99 EndOfFile.EndOfFile.QuadPart = NewSize;
100 Allocation.AllocationSize.QuadPart = NewSize;
101
102 /* First set EOF */
103 Status = ZwSetInformationFile(Database,
105 &EndOfFile,
108 if (NT_SUCCESS(Status))
109 {
110 /* And then, properly set allocation information */
111 Status = ZwSetInformationFile(Database,
113 &Allocation,
116 }
117
118 return Status;
119}
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
@ FileEndOfFileInformation
Definition: from_kernel.h:81
@ FileAllocationInformation
Definition: from_kernel.h:80
Allocation
Definition: exfuncs.h:598

Referenced by DeleteRemoteDatabaseEntry(), GetRemoteDatabaseEntry(), and ReconcileThisDatabaseWithMasterWorker().

◆ WaitForRemoteDatabaseSemaphore()

NTSTATUS WaitForRemoteDatabaseSemaphore ( IN PDEVICE_EXTENSION  DeviceExtension)

Definition at line 371 of file database.c.

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}
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
static ULONG Timeout
Definition: ping.c:61
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163

Referenced by MountMgrDeviceControl(), MountMgrUniqueIdChangeRoutine(), and ReconcileThisDatabaseWithMasterWorker().

◆ WorkerThread()

VOID NTAPI WorkerThread ( IN PDEVICE_OBJECT  DeviceObject,
IN PVOID  Context 
)

Definition at line 1148 of file database.c.

1150{
1151 ULONG i;
1152 KEVENT Event;
1153 KIRQL OldIrql;
1155 HANDLE SafeEvent;
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));
1231 WorkerQueueListEntry);
1232
1233 KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
1234
1235 /* Call it */
1236 WorkItem->WorkerRoutine(WorkItem->Context);
1237
1238 IoFreeWorkItem(WorkItem->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}
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
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 EVENT_ALL_ACCESS
Definition: isotest.c:82
UNICODE_STRING SafeVolumes
Definition: symlink.c:47
KEVENT UnloadEvent
Definition: mountmgr.c:36
NTSYSCALLAPI NTSTATUS NTAPI ZwOpenEvent(_Out_ PHANDLE EventHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)

Referenced by QueueWorkItem().

◆ WriteRemoteDatabaseEntry()

NTSTATUS WriteRemoteDatabaseEntry ( IN HANDLE  Database,
IN LONG  Offset,
IN PDATABASE_ENTRY  Entry 
)

Definition at line 200 of file database.c.

203{
207
208 ByteOffset.QuadPart = Offset;
209 Status = ZwWriteFile(Database,
210 NULL,
211 NULL,
212 NULL,
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}

Referenced by MountMgrVolumeMountPointCreated(), MountMgrVolumeMountPointDeleted(), and ReconcileThisDatabaseWithMasterWorker().

◆ WriteUniqueIdToMaster()

NTSTATUS WriteUniqueIdToMaster ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PDATABASE_ENTRY  DatabaseEntry 
)

Definition at line 489 of file database.c.

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 */
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}
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
NTSTATUS MountMgrCreatePointWorker(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLinkName, IN PUNICODE_STRING DeviceName)
Definition: point.c:35
void * PVOID
Definition: typedefs.h:50
uint16_t * PWCHAR
Definition: typedefs.h:56

Referenced by ReconcileThisDatabaseWithMasterWorker().

Variable Documentation

◆ DatabasePath

◆ OfflinePath

PWSTR OfflinePath = L"\\Registry\\Machine\\System\\MountedDevices\\Offline"

Definition at line 32 of file database.c.

Referenced by IsOffline().

◆ RemoteDatabase

UNICODE_STRING RemoteDatabase = RTL_CONSTANT_STRING(L"\\System Volume Information\\MountPointManagerRemoteDatabase")