ReactOS 0.4.16-dev-1007-g2e85425
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 1913 of file database.c.

1916{
1917 LONG Offset = 0;
1919 PDATABASE_ENTRY Entry, NewEntry;
1921
1922 /* Open the remote database */
1923 Database = OpenRemoteDatabase(DeviceInformation, FALSE);
1924 if (!Database)
1925 {
1926 return;
1927 }
1928
1929 /* Get all the entries */
1930 do
1931 {
1933 if (!Entry)
1934 {
1935 break;
1936 }
1937
1938 /* Not the correct entry, skip it */
1939 if (Entry->UniqueIdLength != OldUniqueId->UniqueIdLength)
1940 {
1941 Offset += Entry->EntrySize;
1942 FreePool(Entry);
1943 continue;
1944 }
1945
1946 /* Not the correct entry, skip it */
1947 if (RtlCompareMemory(OldUniqueId->UniqueId,
1948 (PVOID)((ULONG_PTR)Entry + Entry->UniqueIdOffset),
1949 Entry->UniqueIdLength) != Entry->UniqueIdLength)
1950 {
1951 Offset += Entry->EntrySize;
1952 FreePool(Entry);
1953 continue;
1954 }
1955
1956 /* Here, we have the correct entry */
1957 NewEntry = AllocatePool(Entry->EntrySize + NewUniqueId->UniqueIdLength - OldUniqueId->UniqueIdLength);
1958 if (!NewEntry)
1959 {
1960 Offset += Entry->EntrySize;
1961 FreePool(Entry);
1962 continue;
1963 }
1964
1965 /* Recreate the entry from the previous one */
1966 NewEntry->EntrySize = Entry->EntrySize + NewUniqueId->UniqueIdLength - OldUniqueId->UniqueIdLength;
1967 NewEntry->EntryReferences = Entry->EntryReferences;
1968 NewEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
1969 NewEntry->SymbolicNameLength = Entry->SymbolicNameLength;
1970 NewEntry->UniqueIdOffset = Entry->SymbolicNameLength + sizeof(DATABASE_ENTRY);
1971 NewEntry->UniqueIdLength = NewUniqueId->UniqueIdLength;
1972 RtlCopyMemory((PVOID)((ULONG_PTR)NewEntry + NewEntry->SymbolicNameOffset),
1973 (PVOID)((ULONG_PTR)Entry + Entry->SymbolicNameOffset),
1974 NewEntry->SymbolicNameLength);
1975 RtlCopyMemory((PVOID)((ULONG_PTR)NewEntry + NewEntry->UniqueIdOffset),
1976 NewUniqueId->UniqueId, NewEntry->UniqueIdLength);
1977
1978 /* Delete old entry */
1980 if (!NT_SUCCESS(Status))
1981 {
1982 FreePool(Entry);
1983 FreePool(NewEntry);
1984 break;
1985 }
1986
1987 /* And replace with new one */
1989 FreePool(Entry);
1990 FreePool(NewEntry);
1991 } while (NT_SUCCESS(Status));
1992
1994
1995 return;
1996}
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:1839
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 1792 of file database.c.

1794{
1795 KEVENT Event;
1798
1800
1801 /* Allocate a work item dedicated to migration */
1803 if (!WorkItem)
1804 {
1805 *Database = 0;
1807 }
1808
1810 WorkItem->Event = &Event;
1811 WorkItem->DeviceInformation = DeviceInformation;
1812 WorkItem->WorkItem = IoAllocateWorkItem(DeviceInformation->DeviceExtension->DeviceObject);
1813 if (!WorkItem->WorkItem)
1814 {
1816 *Database = 0;
1818 }
1819
1820 /* And queue it */
1821 IoQueueWorkItem(WorkItem->WorkItem,
1824 WorkItem);
1825
1827 Status = WorkItem->Status;
1828
1829 *Database = (NT_SUCCESS(Status) ? WorkItem->Database : 0);
1830
1832 return Status;
1833}
VOID NTAPI CreateRemoteDatabaseWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
Definition: database.c:1687
#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:38
@ 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 1687 of file database.c.

1689{
1691 HANDLE Database = 0;
1692 UNICODE_STRING DatabaseName;
1696 PDEVICE_INFORMATION DeviceInformation;
1697
1699
1700 /* Extract context */
1701 WorkItem = Context;
1702 DeviceInformation = WorkItem->DeviceInformation;
1703
1704 /* Reconstruct appropriate string */
1705 DatabaseName.Length = 0;
1706 DatabaseName.MaximumLength = DeviceInformation->DeviceName.Length
1708 + sizeof(UNICODE_NULL);
1709 DatabaseName.Buffer = AllocatePool(DatabaseName.MaximumLength);
1710 if (DatabaseName.Buffer == NULL)
1711 {
1713 goto Cleanup;
1714 }
1715
1716 /* Create the required folder (in which the database will be stored
1717 * \System Volume Information at root of the volume
1718 */
1720 if (!NT_SUCCESS(Status))
1721 {
1722 goto Cleanup;
1723 }
1724
1725 /* Finish initiating strings */
1726 RtlAppendUnicodeStringToString(&DatabaseName, &DeviceInformation->DeviceName);
1728 DatabaseName.Buffer[DatabaseName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1729
1730 /* Create database */
1732 &DatabaseName,
1734 NULL,
1735 NULL);
1736
1743 NULL,
1745 0,
1748 NULL,
1749 0,
1751 NULL,
1753 if (!NT_SUCCESS(Status))
1754 {
1756 {
1757 DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n");
1758 }
1759
1760 Database = 0;
1761 goto Cleanup;
1762 }
1763
1764Cleanup:
1765 if (DatabaseName.Buffer)
1766 {
1767 FreePool(DatabaseName.Buffer);
1768 }
1769
1770 if (NT_SUCCESS(Status))
1771 {
1772 DeviceInformation->Migrated = 1;
1773 }
1774 else if (Database != 0)
1775 {
1777 }
1778
1779 IoFreeWorkItem(WorkItem->WorkItem);
1780
1781 WorkItem->WorkItem = NULL;
1782 WorkItem->Status = Status;
1783 WorkItem->Database = Database;
1784
1785 KeSetEvent(WorkItem->Event, 0, FALSE);
1786}
#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:325
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:3011
#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 2003 of file database.c.

2009{
2010 PMOUNTDEV_UNIQUE_ID UniqueId;
2011 UNICODE_STRING RegistryEntry;
2012
2014
2015 if (ValueType != REG_BINARY)
2016 {
2017 return STATUS_SUCCESS;
2018 }
2019
2020 UniqueId = Context;
2021
2022 /* First ensure we have the correct data */
2023 if (UniqueId->UniqueIdLength != ValueLength)
2024 {
2025 return STATUS_SUCCESS;
2026 }
2027
2029 {
2030 return STATUS_SUCCESS;
2031 }
2032
2033 RtlInitUnicodeString(&RegistryEntry, ValueName);
2034
2035 /* Then, it's a drive letter, erase it */
2036 if (IsDriveLetter(&RegistryEntry))
2037 {
2040 ValueName);
2041 }
2042
2043 return STATUS_SUCCESS;
2044}
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:4202
#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:4203
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 2102 of file database.c.

2103{
2105
2108
2111 QueryTable,
2112 UniqueId,
2113 NULL);
2114}
NTSTATUS NTAPI DeleteNoDriveLetterEntryRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: database.c:2069

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 2069 of file database.c.

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

Referenced by DeleteNoDriveLetterEntry().

◆ DeleteRegistryDriveLetter()

VOID DeleteRegistryDriveLetter ( IN PMOUNTDEV_UNIQUE_ID  UniqueId)

Definition at line 2050 of file database.c.

2051{
2053
2056
2059 QueryTable,
2060 UniqueId,
2061 NULL);
2062}
NTSTATUS NTAPI DeleteDriveLetterRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: database.c:2003

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 zero or 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 1462 of file database.c.

1464{
1465 HANDLE Handle;
1470 PDEVICE_INFORMATION VolumeDeviceInformation;
1471 WCHAR FileNameBuffer[0x8], SymbolicNameBuffer[0x64];
1473 FILE_REPARSE_POINT_INFORMATION ReparsePointInformation, SavedReparsePointInformation;
1474
1475 /* Removable devices don't have remote database on them */
1476 if (DeviceInformation->Removable)
1477 {
1478 return;
1479 }
1480
1481 /* Prepare a string with reparse point index */
1482 ReparseFile.Length = 0;
1483 ReparseFile.MaximumLength = DeviceInformation->DeviceName.Length
1485 + sizeof(UNICODE_NULL);
1486 ReparseFile.Buffer = AllocatePool(ReparseFile.MaximumLength);
1487 if (!ReparseFile.Buffer)
1488 {
1489 return;
1490 }
1491
1492 RtlAppendUnicodeStringToString(&ReparseFile, &DeviceInformation->DeviceName);
1494 ReparseFile.Buffer[ReparseFile.Length / sizeof(WCHAR)] = UNICODE_NULL;
1495
1497 &ReparseFile,
1499 NULL,
1500 NULL);
1501
1502 /* Open reparse point */
1509 FreePool(ReparseFile.Buffer);
1510 if (!NT_SUCCESS(Status))
1511 {
1512 DeviceInformation->NoDatabase = FALSE;
1513 return;
1514 }
1515
1516 /* Query reparse point information
1517 * We only pay attention to mout point
1518 */
1520 FileName.Buffer = FileNameBuffer;
1521 FileName.Length = sizeof(FileNameBuffer);
1522 FileName.MaximumLength = sizeof(FileNameBuffer);
1524 Status = ZwQueryDirectoryFile(Handle,
1525 NULL,
1526 NULL,
1527 NULL,
1529 &ReparsePointInformation,
1532 TRUE,
1533 &FileName,
1534 FALSE);
1535 if (!NT_SUCCESS(Status))
1536 {
1537 ZwClose(Handle);
1538 return;
1539 }
1540
1541 RestartScan = TRUE;
1542
1543 /* Query mount points */
1544 while (TRUE)
1545 {
1546 SymbolicName.Length = 0;
1547 SymbolicName.MaximumLength = sizeof(SymbolicNameBuffer);
1548 SymbolicName.Buffer = SymbolicNameBuffer;
1549 RtlCopyMemory(&SavedReparsePointInformation, &ReparsePointInformation, sizeof(FILE_REPARSE_POINT_INFORMATION));
1550
1551 Status = ZwQueryDirectoryFile(Handle,
1552 NULL,
1553 NULL,
1554 NULL,
1556 &ReparsePointInformation,
1559 TRUE,
1560 (RestartScan) ? &FileName : NULL,
1561 RestartScan);
1562 if (!RestartScan)
1563 {
1564 if (ReparsePointInformation.FileReference == SavedReparsePointInformation.FileReference &&
1565 ReparsePointInformation.Tag == SavedReparsePointInformation.Tag)
1566 {
1567 break;
1568 }
1569 }
1570 else
1571 {
1573 }
1574
1575 if (!NT_SUCCESS(Status) || ReparsePointInformation.Tag != IO_REPARSE_TAG_MOUNT_POINT)
1576 {
1577 break;
1578 }
1579
1580 /* Get the volume name associated to the mount point */
1582 &ReparsePointInformation,
1584 &VolumeName);
1585 if (!NT_SUCCESS(Status))
1586 {
1587 continue;
1588 }
1589
1591
1592 /* Get its information */
1593 Status = FindDeviceInfo(DeviceExtension, &SymbolicName,
1594 FALSE, &VolumeDeviceInformation);
1595 if (!NT_SUCCESS(Status))
1596 {
1597 DeviceInformation->NoDatabase = TRUE;
1598 continue;
1599 }
1600
1601 /* If notification are enabled, mark it online */
1602 if (!DeviceInformation->SkipNotifications)
1603 {
1604 PostOnlineNotification(DeviceExtension, &VolumeDeviceInformation->SymbolicName);
1605 }
1606 }
1607
1608 ZwClose(Handle);
1609}
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 1839 of file database.c.

1841{
1847 UNICODE_STRING DeviceRemoteDatabase;
1848
1849 Database = 0;
1850
1851 /* Get database name */
1852 DeviceRemoteDatabase.Length = 0;
1853 DeviceRemoteDatabase.MaximumLength = DeviceInformation->DeviceName.Length
1855 + sizeof(UNICODE_NULL);
1856 DeviceRemoteDatabase.Buffer = AllocatePool(DeviceRemoteDatabase.MaximumLength);
1857 if (!DeviceRemoteDatabase.Buffer)
1858 {
1859 return 0;
1860 }
1861
1862 RtlAppendUnicodeStringToString(&DeviceRemoteDatabase, &DeviceInformation->DeviceName);
1863 RtlAppendUnicodeStringToString(&DeviceRemoteDatabase, &RemoteDatabase);
1864 DeviceRemoteDatabase.Buffer[DeviceRemoteDatabase.Length / sizeof(WCHAR)] = UNICODE_NULL;
1865
1866 /* Open database */
1868 &DeviceRemoteDatabase,
1870 NULL,
1871 NULL);
1872
1873 /* Disable hard errors */
1875
1882 NULL,
1884 0,
1885 (!MigrateDatabase || DeviceInformation->Migrated == 0) ? FILE_OPEN_IF : FILE_OPEN,
1887 NULL,
1888 0,
1890 NULL,
1893 {
1894 DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n");
1895 }
1896
1897 /* If base it to be migrated and was opened successfully, go ahead */
1898 if (MigrateDatabase && NT_SUCCESS(Status))
1899 {
1900 CreateRemoteDatabase(DeviceInformation, &Database);
1901 }
1902
1904 FreePool(DeviceRemoteDatabase.Buffer);
1905
1906 return Database;
1907}
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
NTSTATUS CreateRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, IN OUT PHANDLE Database)
Definition: database.c:1792
#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

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 if (!FileName)
1307 {
1308 UNICODE_STRING Reference;
1309
1310 Reference.Length = Reference.MaximumLength = sizeof(ReparsePointInformation->FileReference);
1311 Reference.Buffer = (PWSTR)&(ReparsePointInformation->FileReference);
1313 &Reference,
1316 NULL);
1317 }
1318 else
1319 {
1321 FileName,
1323 NULL,
1324 NULL);
1325 }
1326
1327 /* Open volume */
1335 if (!NT_SUCCESS(Status))
1336 {
1337 return Status;
1338 }
1339
1340 /* Get the reparse point data */
1342 if (!ReparseDataBuffer)
1343 {
1344 ZwClose(Handle);
1346 }
1347
1349 0,
1350 NULL,
1351 NULL,
1354 NULL,
1355 0,
1356 ReparseDataBuffer,
1358 if (!NT_SUCCESS(Status))
1359 {
1360 FreePool(ReparseDataBuffer);
1361 ZwClose(Handle);
1362 return Status;
1363 }
1364
1365 /* Check that name can fit in buffer */
1366 if (ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength + sizeof(UNICODE_NULL) > SymbolicName->MaximumLength)
1367 {
1368 FreePool(ReparseDataBuffer);
1369 ZwClose(Handle);
1371 }
1372
1373 /* Copy symbolic name */
1374 SymbolicName->Length = ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength;
1376 (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
1377 ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset),
1378 ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength);
1379
1380 FreePool(ReparseDataBuffer);
1381
1382 /* Name has to \ terminated */
1383 if (SymbolicName->Buffer[SymbolicName->Length / sizeof(WCHAR) - 1] != L'\\')
1384 {
1385 ZwClose(Handle);
1387 }
1388
1389 /* So that we can delete it, and match mountmgr requirements */
1390 SymbolicName->Length -= sizeof(WCHAR);
1392
1393 /* Also ensure it's really a volume name... */
1395 {
1396 ZwClose(Handle);
1398 }
1399
1400 /* Now prepare to really get the name */
1401 FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + 2 * sizeof(WCHAR));
1402 if (!FileNameInfo)
1403 {
1404 ZwClose(Handle);
1406 }
1407
1408 Status = ZwQueryInformationFile(Handle,
1410 FileNameInfo,
1411 sizeof(FILE_NAME_INFORMATION) + 2 * sizeof(WCHAR),
1414 {
1415 /* As expected... Reallocate with proper size */
1416 NeededLength = FileNameInfo->FileNameLength;
1417 FreePool(FileNameInfo);
1418
1419 FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + NeededLength);
1420 if (!FileNameInfo)
1421 {
1422 ZwClose(Handle);
1424 }
1425
1426 /* And query name */
1427 Status = ZwQueryInformationFile(Handle,
1429 FileNameInfo,
1430 sizeof(FILE_NAME_INFORMATION) + NeededLength,
1432 }
1433
1434 ZwClose(Handle);
1435
1436 if (!NT_SUCCESS(Status))
1437 {
1438 return Status;
1439 }
1440
1441 /* Return the volume name */
1442 VolumeName->Length = (USHORT)FileNameInfo->FileNameLength;
1443 VolumeName->MaximumLength = (USHORT)FileNameInfo->FileNameLength + sizeof(WCHAR);
1445 if (!VolumeName->Buffer)
1446 {
1448 }
1449
1450 RtlCopyMemory(VolumeName->Buffer, FileNameInfo->FileName, FileNameInfo->FileNameLength);
1451 VolumeName->Buffer[FileNameInfo->FileNameLength / sizeof(WCHAR)] = UNICODE_NULL;
1452
1453 FreePool(FileNameInfo);
1454
1455 return STATUS_SUCCESS;
1456}
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::@334::@337 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 1661 of file database.c.

1662{
1663 PLIST_ENTRY NextEntry;
1664 PDEVICE_INFORMATION DeviceInformation;
1665
1666 /* Browse all the devices */
1667 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1668 NextEntry != &(DeviceExtension->DeviceListHead);
1669 NextEntry = NextEntry->Flink)
1670 {
1671 DeviceInformation = CONTAINING_RECORD(NextEntry,
1673 DeviceListEntry);
1674 /* If it's not removable, then, it might have a database to sync */
1675 if (!DeviceInformation->Removable)
1676 {
1677 ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
1678 }
1679 }
1680}
VOID ReconcileThisDatabaseWithMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1615
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 1615 of file database.c.

1617{
1619
1620 /* Removable devices don't have remote database */
1621 if (DeviceInformation->Removable)
1622 {
1623 return;
1624 }
1625
1626 /* Allocate a work item */
1628 if (!WorkItem)
1629 {
1630 return;
1631 }
1632
1633 WorkItem->WorkItem = IoAllocateWorkItem(DeviceExtension->DeviceObject);
1634 if (!WorkItem->WorkItem)
1635 {
1637 return;
1638 }
1639
1640 /* And queue it */
1642 WorkItem->DeviceExtension = DeviceExtension;
1643 WorkItem->DeviceInformation = DeviceInformation;
1644 QueueWorkItem(DeviceExtension, WorkItem, &(WorkItem->DeviceExtension));
1645
1646 /* If the worker thread isn't started yet, automatic drive letter is
1647 * enabled but automount disabled, manually set mounted volumes online.
1648 * Otherwise, they will be set online during database reconciliation. */
1649 if (DeviceExtension->WorkerThreadStatus == 0 &&
1650 DeviceExtension->AutomaticDriveLetter &&
1651 DeviceExtension->NoAutoMount)
1652 {
1653 OnlineMountedVolumes(DeviceExtension, DeviceInformation);
1654 }
1655}
VOID OnlineMountedVolumes(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1462
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: d3dkmdt.h:49
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")