ReactOS 0.4.15-dev-7788-g1ad9096
mntmgr.h File Reference
#include <ntifs.h>
#include <mountdev.h>
#include <ntddvol.h>
#include <ntdddisk.h>
#include <wdmguid.h>
#include <ndk/psfuncs.h>
#include <section_attribs.h>
Include dependency graph for mntmgr.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _DEVICE_EXTENSION
 
struct  _DEVICE_INFORMATION
 
struct  _SYMLINK_INFORMATION
 
struct  _SAVED_LINK_INFORMATION
 
struct  _UNIQUE_ID_REPLICATE
 
struct  _DATABASE_ENTRY
 
struct  _ASSOCIATED_DEVICE_ENTRY
 
struct  _DEVICE_INFORMATION_ENTRY
 
struct  _ONLINE_NOTIFICATION_WORK_ITEM
 
struct  _RECONCILE_WORK_ITEM_CONTEXT
 
struct  _RECONCILE_WORK_ITEM
 
struct  _MIGRATE_WORK_ITEM
 
struct  _UNIQUE_ID_WORK_ITEM
 

Macros

#define AllocatePool(Size)   ExAllocatePoolWithTag(PagedPool, Size, 'AtnM')
 
#define FreePool(P)   ExFreePoolWithTag(P, 'AtnM')
 
#define MAX(a, b)   ((a > b) ? a : b)
 
#define LETTER_POSITION   0xC
 
#define COLON_POSITION   0xD
 
#define DRIVE_LETTER_LENGTH   0x1C
 

Typedefs

typedef struct _DEVICE_EXTENSION DEVICE_EXTENSION
 
typedef struct _DEVICE_EXTENSIONPDEVICE_EXTENSION
 
typedef struct _DEVICE_INFORMATION DEVICE_INFORMATION
 
typedef struct _DEVICE_INFORMATIONPDEVICE_INFORMATION
 
typedef struct _SYMLINK_INFORMATION SYMLINK_INFORMATION
 
typedef struct _SYMLINK_INFORMATIONPSYMLINK_INFORMATION
 
typedef struct _SAVED_LINK_INFORMATION SAVED_LINK_INFORMATION
 
typedef struct _SAVED_LINK_INFORMATIONPSAVED_LINK_INFORMATION
 
typedef struct _UNIQUE_ID_REPLICATE UNIQUE_ID_REPLICATE
 
typedef struct _UNIQUE_ID_REPLICATEPUNIQUE_ID_REPLICATE
 
typedef struct _DATABASE_ENTRY DATABASE_ENTRY
 
typedef struct _DATABASE_ENTRYPDATABASE_ENTRY
 
typedef struct _ASSOCIATED_DEVICE_ENTRY ASSOCIATED_DEVICE_ENTRY
 
typedef struct _ASSOCIATED_DEVICE_ENTRYPASSOCIATED_DEVICE_ENTRY
 
typedef struct _DEVICE_INFORMATION_ENTRY DEVICE_INFORMATION_ENTRY
 
typedef struct _DEVICE_INFORMATION_ENTRYPDEVICE_INFORMATION_ENTRY
 
typedef struct _ONLINE_NOTIFICATION_WORK_ITEM ONLINE_NOTIFICATION_WORK_ITEM
 
typedef struct _ONLINE_NOTIFICATION_WORK_ITEMPONLINE_NOTIFICATION_WORK_ITEM
 
typedef struct _RECONCILE_WORK_ITEM_CONTEXT RECONCILE_WORK_ITEM_CONTEXT
 
typedef struct _RECONCILE_WORK_ITEM_CONTEXTPRECONCILE_WORK_ITEM_CONTEXT
 
typedef struct _RECONCILE_WORK_ITEM RECONCILE_WORK_ITEM
 
typedef struct _RECONCILE_WORK_ITEMPRECONCILE_WORK_ITEM
 
typedef struct _MIGRATE_WORK_ITEM MIGRATE_WORK_ITEM
 
typedef struct _MIGRATE_WORK_ITEMPMIGRATE_WORK_ITEM
 
typedef struct _UNIQUE_ID_WORK_ITEM UNIQUE_ID_WORK_ITEM
 
typedef struct _UNIQUE_ID_WORK_ITEMPUNIQUE_ID_WORK_ITEM
 

Functions

VOID NTAPI MountMgrCancel (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS MountMgrMountedDeviceArrival (IN PDEVICE_EXTENSION Extension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN FromVolume)
 
VOID MountMgrMountedDeviceRemoval (IN PDEVICE_EXTENSION Extension, IN PUNICODE_STRING DeviceName)
 
NTSTATUS FindDeviceInfo (IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
 
VOID MountMgrFreeDeadDeviceInfo (IN PDEVICE_INFORMATION DeviceInformation)
 
NTSTATUS QueryDeviceInformation (IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING DeviceName OPTIONAL, OUT PMOUNTDEV_UNIQUE_ID *UniqueId OPTIONAL, OUT PBOOLEAN Removable OPTIONAL, OUT PBOOLEAN GptDriveLetter OPTIONAL, OUT PBOOLEAN HasGuid OPTIONAL, IN OUT LPGUID StableGuid OPTIONAL, OUT PBOOLEAN Valid OPTIONAL)
 
BOOLEAN HasDriveLetter (IN PDEVICE_INFORMATION DeviceInformation)
 
BOOLEAN MountmgrReadNoAutoMount (IN PUNICODE_STRING RegistryPath)
 
VOID ReconcileThisDatabaseWithMaster (IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
 
NTSTATUS WaitForRemoteDatabaseSemaphore (IN PDEVICE_EXTENSION DeviceExtension)
 
VOID ReleaseRemoteDatabaseSemaphore (IN PDEVICE_EXTENSION DeviceExtension)
 
VOID ChangeRemoteDatabaseUniqueId (IN PDEVICE_INFORMATION DeviceInformation, IN PMOUNTDEV_UNIQUE_ID OldUniqueId, IN PMOUNTDEV_UNIQUE_ID NewUniqueId)
 
VOID ReconcileAllDatabasesWithMaster (IN PDEVICE_EXTENSION DeviceExtension)
 
VOID DeleteFromLocalDatabase (IN PUNICODE_STRING SymbolicLink, IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
VOID DeleteRegistryDriveLetter (IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
VOID DeleteNoDriveLetterEntry (IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
NTSTATUS QueryVolumeName (IN HANDLE RootDirectory, IN PFILE_REPARSE_POINT_INFORMATION ReparsePointInformation, IN PUNICODE_STRING FileName OPTIONAL, OUT PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING VolumeName)
 
HANDLE OpenRemoteDatabase (IN PDEVICE_INFORMATION DeviceInformation, IN BOOLEAN MigrateDatabase)
 
PDATABASE_ENTRY GetRemoteDatabaseEntry (IN HANDLE Database, IN LONG StartingOffset)
 
NTSTATUS WriteRemoteDatabaseEntry (IN HANDLE Database, IN LONG Offset, IN PDATABASE_ENTRY Entry)
 
NTSTATUS CloseRemoteDatabase (IN HANDLE Database)
 
NTSTATUS AddRemoteDatabaseEntry (IN HANDLE Database, IN PDATABASE_ENTRY Entry)
 
NTSTATUS DeleteRemoteDatabaseEntry (IN HANDLE Database, IN LONG StartingOffset)
 
VOID NTAPI ReconcileThisDatabaseWithMasterWorker (IN PVOID Parameter)
 
VOID IssueUniqueIdChangeNotifyWorker (IN PUNIQUE_ID_WORK_ITEM WorkItem, IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
VOID WaitForOnlinesToComplete (IN PDEVICE_EXTENSION DeviceExtension)
 
VOID RegisterForTargetDeviceNotification (IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
 
VOID SendOnlineNotification (IN PUNICODE_STRING SymbolicName)
 
VOID IssueUniqueIdChangeNotify (IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
VOID PostOnlineNotification (IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName)
 
VOID MountMgrNotify (IN PDEVICE_EXTENSION DeviceExtension)
 
VOID MountMgrNotifyNameChange (IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN BOOLEAN ValidateVolume)
 
VOID MountMgrUniqueIdChangeRoutine (IN PDEVICE_EXTENSION DeviceExtension, IN PMOUNTDEV_UNIQUE_ID OldUniqueId, IN PMOUNTDEV_UNIQUE_ID NewUniqueId)
 
VOID CreateNoDriveLetterEntry (IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
BOOLEAN HasNoDriveLetterEntry (IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
VOID UpdateReplicatedUniqueIds (IN PDEVICE_INFORMATION DeviceInformation, IN PDATABASE_ENTRY DatabaseEntry)
 
BOOLEAN IsUniqueIdPresent (IN PDEVICE_EXTENSION DeviceExtension, IN PDATABASE_ENTRY DatabaseEntry)
 
NTSTATUS MountMgrCreatePointWorker (IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLinkName, IN PUNICODE_STRING DeviceName)
 
NTSTATUS QueryPointsFromSymbolicLinkName (IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN PIRP Irp)
 
NTSTATUS QueryPointsFromMemory (IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL, IN PUNICODE_STRING SymbolicName OPTIONAL)
 
NTSTATUS GlobalCreateSymbolicLink (IN PUNICODE_STRING DosName, IN PUNICODE_STRING DeviceName)
 
NTSTATUS GlobalDeleteSymbolicLink (IN PUNICODE_STRING DosName)
 
NTSTATUS QuerySuggestedLinkName (IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING SuggestedLinkName, OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
 
NTSTATUS QuerySymbolicLinkNamesFromStorage (IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation, IN PUNICODE_STRING SuggestedLinkName, IN BOOLEAN UseOnlyIfThereAreNoOtherLinks, OUT PUNICODE_STRING *SymLinks, OUT PULONG SymLinkCount, IN BOOLEAN HasGuid, IN LPGUID Guid)
 
PSAVED_LINK_INFORMATION RemoveSavedLinks (IN PDEVICE_EXTENSION DeviceExtension, IN PMOUNTDEV_UNIQUE_ID UniqueId)
 
BOOLEAN RedirectSavedLink (IN PSAVED_LINK_INFORMATION SavedLinkInformation, IN PUNICODE_STRING DosName, IN PUNICODE_STRING NewLink)
 
VOID SendLinkCreated (IN PUNICODE_STRING SymbolicName)
 
NTSTATUS CreateNewVolumeName (OUT PUNICODE_STRING VolumeName, IN PGUID VolumeGuid OPTIONAL)
 
BOOLEAN IsDriveLetter (PUNICODE_STRING SymbolicName)
 
VOID DeleteSymbolicLinkNameFromMemory (IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicLink, IN BOOLEAN MarkOffline)
 
NTSTATUS MountMgrQuerySymbolicLink (IN PUNICODE_STRING SymbolicName, IN OUT PUNICODE_STRING LinkTarget)
 

Variables

UNICODE_STRING DosDevicesMount
 
PDEVICE_OBJECT gdeviceObject
 
UNICODE_STRING ReparseIndex
 
UNICODE_STRING DeviceFloppy
 
UNICODE_STRING DeviceMount
 
UNICODE_STRING DeviceCdRom
 
UNICODE_STRING SafeVolumes
 
UNICODE_STRING DosDevices
 
UNICODE_STRING DosGlobal
 
UNICODE_STRING Global
 
UNICODE_STRING Volume
 
KEVENT UnloadEvent
 
LONG Unloading
 
DRIVER_INITIALIZE DriverEntry
 
PWSTR DatabasePath
 
PWSTR OfflinePath
 
DRIVER_DISPATCH MountMgrDeviceControl
 

Macro Definition Documentation

◆ AllocatePool

#define AllocatePool (   Size)    ExAllocatePoolWithTag(PagedPool, Size, 'AtnM')

Definition at line 153 of file mntmgr.h.

◆ COLON_POSITION

#define COLON_POSITION   0xD

Definition at line 160 of file mntmgr.h.

◆ DRIVE_LETTER_LENGTH

#define DRIVE_LETTER_LENGTH   0x1C

Definition at line 161 of file mntmgr.h.

◆ FreePool

#define FreePool (   P)    ExFreePoolWithTag(P, 'AtnM')

Definition at line 154 of file mntmgr.h.

◆ LETTER_POSITION

#define LETTER_POSITION   0xC

Definition at line 159 of file mntmgr.h.

◆ MAX

#define MAX (   a,
  b 
)    ((a > b) ? a : b)

Definition at line 157 of file mntmgr.h.

Typedef Documentation

◆ ASSOCIATED_DEVICE_ENTRY

◆ DATABASE_ENTRY

◆ DEVICE_EXTENSION

◆ DEVICE_INFORMATION

◆ DEVICE_INFORMATION_ENTRY

◆ MIGRATE_WORK_ITEM

◆ ONLINE_NOTIFICATION_WORK_ITEM

◆ PASSOCIATED_DEVICE_ENTRY

◆ PDATABASE_ENTRY

◆ PDEVICE_EXTENSION

◆ PDEVICE_INFORMATION

◆ PDEVICE_INFORMATION_ENTRY

◆ PMIGRATE_WORK_ITEM

◆ PONLINE_NOTIFICATION_WORK_ITEM

◆ PRECONCILE_WORK_ITEM

◆ PRECONCILE_WORK_ITEM_CONTEXT

◆ PSAVED_LINK_INFORMATION

◆ PSYMLINK_INFORMATION

◆ PUNIQUE_ID_REPLICATE

◆ PUNIQUE_ID_WORK_ITEM

◆ RECONCILE_WORK_ITEM

◆ RECONCILE_WORK_ITEM_CONTEXT

◆ SAVED_LINK_INFORMATION

◆ SYMLINK_INFORMATION

◆ UNIQUE_ID_REPLICATE

◆ UNIQUE_ID_WORK_ITEM

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:32
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().

◆ CreateNewVolumeName()

NTSTATUS CreateNewVolumeName ( OUT PUNICODE_STRING  VolumeName,
IN PGUID VolumeGuid  OPTIONAL 
)

Definition at line 462 of file symlink.c.

464{
465 GUID Guid;
468
469 /* If no GUID was provided, then create one */
470 if (!VolumeGuid)
471 {
473 if (!NT_SUCCESS(Status))
474 {
475 return Status;
476 }
477 }
478 else
479 {
480 RtlCopyMemory(&Guid, VolumeGuid, sizeof(GUID));
481 }
482
483 /* Convert GUID to string */
485 if (!NT_SUCCESS(Status))
486 {
487 return Status;
488 }
489
490 /* Size for volume namespace, literal GUID, and null char */
491 VolumeName->MaximumLength = 0x14 + 0x4C + sizeof(UNICODE_NULL);
492 VolumeName->Buffer = AllocatePool(0x14 + 0x4C + sizeof(UNICODE_NULL));
493 if (!VolumeName->Buffer)
494 {
496 }
497 else
498 {
503 }
504
505 ExFreePoolWithTag(GuidString.Buffer, 0);
506
507 return Status;
508}
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
NTKERNELAPI NTSTATUS ExUuidCreate(OUT UUID *Uuid)
Definition: uuid.c:380
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static PWSTR GuidString
Definition: apphelp.c:93
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define UNICODE_NULL
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by MountMgrMountedDeviceArrival(), and QuerySymbolicLinkNamesFromStorage().

◆ CreateNoDriveLetterEntry()

VOID CreateNoDriveLetterEntry ( IN PMOUNTDEV_UNIQUE_ID  UniqueId)

Definition at line 269 of file uniqueid.c.

270{
271 UUID Guid;
274
275 /* Entry with no drive letter are made that way:
276 * Instead of having a path with the letter,
277 * you have GUID with the unique ID.
278 */
280 {
281 return;
282 }
283
284 /* Convert to string */
286 {
287 return;
288 }
289
290 /* No letter entries must start with #, so allocate a proper string */
291 String = AllocatePool(GuidString.Length + 2 * sizeof(WCHAR));
292 if (!String)
293 {
294 ExFreePoolWithTag(GuidString.Buffer, 0);
295 return;
296 }
297
298 /* Write the complete string */
299 String[0] = L'#';
300 RtlCopyMemory(String + 1, GuidString.Buffer, GuidString.Length);
301 String[GuidString.Length / sizeof(WCHAR)] = UNICODE_NULL;
302
303 /* Don't need that one anymore */
304 ExFreePoolWithTag(GuidString.Buffer, 0);
305
306 /* Write the entry */
309 String,
311 UniqueId->UniqueId,
312 UniqueId->UniqueIdLength);
313
315
316 return;
317}
PWSTR DatabasePath
Definition: database.c:31
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
#define REG_BINARY
Definition: nt_native.h:1496
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define L(x)
Definition: ntvdm.h:50
uint16_t * PWCHAR
Definition: typedefs.h:56
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433

Referenced by CreateNewDriveLetterName(), MountMgrDeletePoints(), MountMgrDeletePointsDbOnly(), MountMgrMountedDeviceArrival(), MountMgrNextDriveLetterWorker(), and ProcessSuggestedDriveLetters().

◆ 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:4208
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by MountMgrMountedDeviceArrival().

◆ 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().

◆ 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().

◆ DeleteSymbolicLinkNameFromMemory()

VOID DeleteSymbolicLinkNameFromMemory ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PUNICODE_STRING  SymbolicLink,
IN BOOLEAN  MarkOffline 
)

Definition at line 864 of file symlink.c.

867{
868 PLIST_ENTRY DeviceEntry, SymbolEntry;
869 PDEVICE_INFORMATION DeviceInformation;
870 PSYMLINK_INFORMATION SymlinkInformation;
871
872 /* First of all, ensure we have devices */
873 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
874 {
875 return;
876 }
877
878 /* Then, look for the symbolic name */
879 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
880 DeviceEntry != &(DeviceExtension->DeviceListHead);
881 DeviceEntry = DeviceEntry->Flink)
882 {
883 DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
884
885 for (SymbolEntry = DeviceInformation->SymbolicLinksListHead.Flink;
886 SymbolEntry != &(DeviceInformation->SymbolicLinksListHead);
887 SymbolEntry = SymbolEntry->Flink)
888 {
889 SymlinkInformation = CONTAINING_RECORD(SymbolEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
890
891 /* One we have found it */
892 if (RtlCompareUnicodeString(SymbolicLink, &(SymlinkInformation->Name), TRUE) == 0)
893 {
894 /* Check if caller just want it to be offline */
895 if (MarkOffline)
896 {
897 SymlinkInformation->Online = FALSE;
898 }
899 else
900 {
901 /* If not, delete it & notify */
902 SendLinkDeleted(&(DeviceInformation->SymbolicName), SymbolicLink);
903 RemoveEntryList(&(SymlinkInformation->SymbolicLinksListEntry));
904
905 FreePool(SymlinkInformation->Name.Buffer);
906 FreePool(SymlinkInformation);
907 }
908
909 /* No need to go farther */
910 return;
911 }
912 }
913 }
914
915 return;
916}
#define TRUE
Definition: types.h:120
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
UNICODE_STRING SymbolicName
Definition: mntmgr.h:48
LIST_ENTRY SymbolicLinksListHead
Definition: mntmgr.h:45
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by MountMgrDeletePoints(), and MountMgrDeletePointsDbOnly().

◆ FindDeviceInfo()

NTSTATUS FindDeviceInfo ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PUNICODE_STRING  SymbolicName,
IN BOOLEAN  DeviceNameGiven,
OUT PDEVICE_INFORMATION DeviceInformation 
)

Definition at line 636 of file mountmgr.c.

640{
642 PLIST_ENTRY NextEntry;
645
646 /* If a device name was given, use it */
647 if (DeviceNameGiven)
648 {
651 }
652 else
653 {
654 /* Otherwise, query it */
656 &DeviceName,
657 NULL, NULL,
658 NULL, NULL,
659 NULL, NULL);
660 if (!NT_SUCCESS(Status))
661 {
662 return Status;
663 }
664 }
665
666 /* Look for device information matching devive */
667 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
668 NextEntry != &(DeviceExtension->DeviceListHead);
669 NextEntry = NextEntry->Flink)
670 {
671 DeviceInfo = CONTAINING_RECORD(NextEntry,
673 DeviceListEntry);
674
675 if (RtlEqualUnicodeString(&DeviceName, &(DeviceInfo->DeviceName), TRUE))
676 {
677 break;
678 }
679 }
680
681 /* Release our buffer if required */
682 if (!DeviceNameGiven)
683 {
684 FreePool(DeviceName.Buffer);
685 }
686
687 /* Return found information */
688 if (NextEntry == &(DeviceExtension->DeviceListHead))
689 {
691 }
692
693 *DeviceInformation = DeviceInfo;
694 return STATUS_SUCCESS;
695}
NTSTATUS QueryDeviceInformation(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING DeviceName OPTIONAL, OUT PMOUNTDEV_UNIQUE_ID *UniqueId OPTIONAL, OUT PBOOLEAN Removable OPTIONAL, OUT PBOOLEAN GptDriveLetter OPTIONAL, OUT PBOOLEAN HasGuid OPTIONAL, IN OUT LPGUID StableGuid OPTIONAL, OUT PBOOLEAN Valid OPTIONAL)
Definition: mountmgr.c:190
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4677
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275

Referenced by MountMgrKeepLinksWhenOffline(), MountMgrQueryDosVolumePath(), MountMgrQueryDosVolumePaths(), MountMgrVolumeMountPointChanged(), MountMgrVolumeMountPointCreated(), MountMgrVolumeMountPointDeleted(), OnlineMountedVolumes(), QueryUniqueIdFromMaster(), 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:731
_In_ UCHAR EntrySize
Definition: iofuncs.h:642

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

◆ GlobalCreateSymbolicLink()

NTSTATUS GlobalCreateSymbolicLink ( IN PUNICODE_STRING  DosName,
IN PUNICODE_STRING  DeviceName 
)

Definition at line 111 of file symlink.c.

113{
115 UNICODE_STRING GlobalName;
116
117 /* First create the global string */
118 Status = CreateStringWithGlobal(DosName, &GlobalName);
119 if (!NT_SUCCESS(Status))
120 {
121 return Status;
122 }
123
124 /* Then, create the symlink */
125 Status = IoCreateSymbolicLink(&GlobalName, DeviceName);
126
127 FreePool(GlobalName.Buffer);
128
129 return Status;
130}
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1269

Referenced by CreateNewDriveLetterName(), DriverEntry(), MountMgrCreatePointWorker(), MountMgrMountedDeviceArrival(), and RedirectSavedLink().

◆ GlobalDeleteSymbolicLink()

NTSTATUS GlobalDeleteSymbolicLink ( IN PUNICODE_STRING  DosName)

Definition at line 136 of file symlink.c.

137{
139 UNICODE_STRING GlobalName;
140
141 /* Recreate the string (to find the link) */
142 Status = CreateStringWithGlobal(DosName, &GlobalName);
143 if (!NT_SUCCESS(Status))
144 {
145 return Status;
146 }
147
148 /* And delete the link */
149 Status = IoDeleteSymbolicLink(&GlobalName);
150
151 FreePool(GlobalName.Buffer);
152
153 return Status;
154}

Referenced by MountMgrCreatePointWorker(), MountMgrDeletePoints(), MountMgrFreeMountedDeviceInfo(), MountMgrFreeSavedLink(), MountMgrMountedDeviceArrival(), MountMgrMountedDeviceRemoval(), MountMgrUnload(), and RedirectSavedLink().

◆ HasDriveLetter()

BOOLEAN HasDriveLetter ( IN PDEVICE_INFORMATION  DeviceInformation)

Definition at line 83 of file mountmgr.c.

84{
85 PLIST_ENTRY NextEntry;
86 PSYMLINK_INFORMATION SymlinkInfo;
87
88 /* Browse all the symlinks to check if there is at least a drive letter */
89 for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
90 NextEntry != &DeviceInformation->SymbolicLinksListHead;
91 NextEntry = NextEntry->Flink)
92 {
93 SymlinkInfo = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
94
95 if (IsDriveLetter(&SymlinkInfo->Name) && SymlinkInfo->Online)
96 {
97 return TRUE;
98 }
99 }
100
101 return FALSE;
102}
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:922

Referenced by MountMgrCreatePointWorker(), and ProcessSuggestedDriveLetters().

◆ HasNoDriveLetterEntry()

BOOLEAN HasNoDriveLetterEntry ( IN PMOUNTDEV_UNIQUE_ID  UniqueId)

Definition at line 354 of file uniqueid.c.

355{
356 BOOLEAN EntryPresent = FALSE;
358
361 QueryTable[0].EntryContext = &EntryPresent;
362
366 UniqueId,
367 NULL);
368
369 return EntryPresent;
370}
unsigned char BOOLEAN
NTSTATUS NTAPI CheckForNoDriveLetterEntry(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: uniqueid.c:324

Referenced by MountMgrMountedDeviceArrival(), MountMgrNextDriveLetterWorker(), and ProcessSuggestedDriveLetters().

◆ IsDriveLetter()

BOOLEAN IsDriveLetter ( PUNICODE_STRING  SymbolicName)

Definition at line 922 of file symlink.c.

923{
925
926 /* We must have a precise length */
927 if (SymbolicName->Length != DosDevices.Length + 2 * sizeof(WCHAR))
928 {
929 return FALSE;
930 }
931
932 /* Must start with the DosDevices prefix */
934 {
935 return FALSE;
936 }
937
938 /* Check if letter is correct */
940 if ((Letter < L'A' || Letter > L'Z') && Letter != (WCHAR)-1)
941 {
942 return FALSE;
943 }
944
945 /* And finally it must end with a colon */
947 if (Colon != L':')
948 {
949 return FALSE;
950 }
951
952 return TRUE;
953}
WCHAR Letter
@ Colon
Definition: asmpp.cpp:43
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)

Referenced by DeleteDriveLetterRoutine(), HasDriveLetter(), MountMgrCreatePointWorker(), MountMgrDeletePoints(), MountMgrDeletePointsDbOnly(), MountMgrMountedDeviceArrival(), MountMgrNextDriveLetterWorker(), and QuerySymbolicLinkNamesFromStorage().

◆ IssueUniqueIdChangeNotify()

VOID IssueUniqueIdChangeNotify ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PUNICODE_STRING  DeviceName,
IN PMOUNTDEV_UNIQUE_ID  UniqueId 
)

Definition at line 660 of file notify.c.

663{
665 PVOID IrpBuffer = NULL;
669
670 /* Get the associated device object */
673 &FileObject,
674 &DeviceObject);
675 if (!NT_SUCCESS(Status))
676 {
677 return;
678 }
679
680 /* And then, get attached device */
682
684
685 /* Allocate a work item */
687 if (!WorkItem)
688 {
690 return;
691 }
692
693 WorkItem->Event = NULL;
694 WorkItem->WorkItem = IoAllocateWorkItem(DeviceExtension->DeviceObject);
695 if (!WorkItem->WorkItem)
696 {
698 goto Cleanup;
699 }
700
701 WorkItem->DeviceExtension = DeviceExtension;
702 WorkItem->StackSize = DeviceObject->StackSize;
703 /* Already provide the IRP */
704 WorkItem->Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
705
707
708 if (!WorkItem->Irp)
709 {
710 goto Cleanup;
711 }
712
713 /* Ensure it has enough space */
714 IrpBuffer = AllocatePool(sizeof(MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT) + 1024);
715 if (!IrpBuffer)
716 {
717 goto Cleanup;
718 }
719
720 WorkItem->DeviceName.Length = DeviceName->Length;
721 WorkItem->DeviceName.MaximumLength = DeviceName->Length + sizeof(WCHAR);
722 WorkItem->DeviceName.Buffer = AllocatePool(WorkItem->DeviceName.MaximumLength);
723 if (!WorkItem->DeviceName.Buffer)
724 {
725 goto Cleanup;
726 }
727
728 RtlCopyMemory(WorkItem->DeviceName.Buffer, DeviceName->Buffer, DeviceName->Length);
729 WorkItem->DeviceName.Buffer[DeviceName->Length / sizeof(WCHAR)] = UNICODE_NULL;
730
731 WorkItem->IrpBuffer = IrpBuffer;
732 WorkItem->IrpBufferLength = sizeof(MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT) + 1024;
733
734 /* Add the worker in the list */
735 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
736 InsertHeadList(&(DeviceExtension->UniqueIdWorkerItemListHead), &(WorkItem->UniqueIdWorkerItemListEntry));
737 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
738
739 /* And call the worker */
741
742 return;
743
744Cleanup:
745 if (IrpBuffer)
746 {
747 FreePool(IrpBuffer);
748 }
749
750 if (WorkItem->Irp)
751 {
752 IoFreeIrp(WorkItem->Irp);
753 }
754
755 if (WorkItem->WorkItem)
756 {
757 IoFreeWorkItem(WorkItem->WorkItem);
758 }
759
760 if (WorkItem)
761 {
763 }
764}
static const WCHAR Cleanup[]
Definition: register.c:80
VOID IssueUniqueIdChangeNotifyWorker(IN PUNIQUE_ID_WORK_ITEM WorkItem, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: notify.c:590
#define InsertHeadList(ListHead, Entry)
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
struct _MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT
#define KernelMode
Definition: asm.h:34
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
#define IO_NO_INCREMENT
Definition: iotypes.h:598
* PFILE_OBJECT
Definition: iotypes.h:1998
@ Executive
Definition: ketypes.h:415
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by MountMgrMountedDeviceArrival().

◆ IssueUniqueIdChangeNotifyWorker()

VOID IssueUniqueIdChangeNotifyWorker ( IN PUNIQUE_ID_WORK_ITEM  WorkItem,
IN PMOUNTDEV_UNIQUE_ID  UniqueId 
)

Definition at line 590 of file notify.c.

592{
593 PIRP Irp;
598
599 /* Get the device object */
602 &FileObject,
603 &DeviceObject);
604 if (!NT_SUCCESS(Status))
605 {
607 return;
608 }
609
610 /* And then, the attached device */
612
613 /* Initialize the IRP */
614 Irp = WorkItem->Irp;
615 IoInitializeIrp(Irp, IoSizeOfIrp(WorkItem->StackSize), (CCHAR)WorkItem->StackSize);
616
617 if (InterlockedExchange((PLONG)&(WorkItem->Event), 0) != 0)
618 {
622 return;
623 }
624
625 Irp->AssociatedIrp.SystemBuffer = WorkItem->IrpBuffer;
626 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
627 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, UniqueId, UniqueId->UniqueIdLength + sizeof(USHORT));
628
630
631 Stack->Parameters.DeviceIoControl.InputBufferLength = UniqueId->UniqueIdLength + sizeof(USHORT);
632 Stack->Parameters.DeviceIoControl.OutputBufferLength = WorkItem->IrpBufferLength;
633 Stack->Parameters.DeviceIoControl.Type3InputBuffer = 0;
634 Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY;
635 Stack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
636
637 Status = IoSetCompletionRoutineEx(WorkItem->DeviceExtension->DeviceObject,
638 Irp,
640 WorkItem,
641 TRUE, TRUE, TRUE);
642 if (!NT_SUCCESS(Status))
643 {
647 return;
648 }
649
650 /* Call the driver */
654}
#define InterlockedExchange
Definition: armddk.h:54
_In_ PIRP Irp
Definition: csq.h:116
VOID RemoveWorkItem(IN PUNIQUE_ID_WORK_ITEM WorkItem)
Definition: notify.c:480
NTSTATUS NTAPI UniqueIdChangeNotifyCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
Definition: notify.c:568
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTSTATUS NTAPI IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PIO_COMPLETION_ROUTINE CompletionRoutine, IN PVOID Context, IN BOOLEAN InvokeOnSuccess, IN BOOLEAN InvokeOnError, IN BOOLEAN InvokeOnCancel)
Definition: iocomp.c:220
#define IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY
Definition: imports.h:86
VOID NTAPI IoInitializeIrp(IN PIRP Irp, IN USHORT PacketSize, IN CCHAR StackSize)
Definition: irp.c:1854
#define IoCallDriver
Definition: irp.c:1225
unsigned short USHORT
Definition: pedump.c:61
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
int32_t * PLONG
Definition: typedefs.h:58
char CCHAR
Definition: typedefs.h:51
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IoSizeOfIrp(_StackSize)

Referenced by IssueUniqueIdChangeNotify(), and UniqueIdChangeNotifyWorker().

◆ IsUniqueIdPresent()

BOOLEAN IsUniqueIdPresent ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PDATABASE_ENTRY  DatabaseEntry 
)

Definition at line 221 of file uniqueid.c.

223{
224 PLIST_ENTRY NextEntry;
225 PDEVICE_INFORMATION DeviceInformation;
226
227 /* If no device, no unique ID (O'rly?!)
228 * ./)/).
229 * (°-°)
230 * (___) ORLY?
231 * " "
232 */
233 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
234 {
235 return FALSE;
236 }
237
238 /* Now we know that we have devices, find the one */
239 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
240 NextEntry != &(DeviceExtension->DeviceListHead);
241 NextEntry = NextEntry->Flink)
242 {
243 DeviceInformation = CONTAINING_RECORD(NextEntry,
245 DeviceListEntry);
246
247 if (DeviceInformation->UniqueId->UniqueIdLength != DatabaseEntry->UniqueIdLength)
248 {
249 continue;
250 }
251
252 /* It's matching! */
253 if (RtlCompareMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
254 DeviceInformation->UniqueId->UniqueId,
255 DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
256 {
257 return TRUE;
258 }
259 }
260
261 /* No luck... */
262 return FALSE;
263}
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:49
USHORT UniqueIdLength
Definition: imports.h:138
UCHAR UniqueId[1]
Definition: imports.h:139

Referenced by ReconcileThisDatabaseWithMasterWorker().

◆ MountMgrCancel()

VOID NTAPI MountMgrCancel ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 1676 of file mountmgr.c.

1678{
1680
1681 RemoveEntryList(&(Irp->Tail.Overlay.ListEntry));
1682
1683 IoReleaseCancelSpinLock(Irp->CancelIrql);
1684
1685 Irp->IoStatus.Information = 0;
1686 Irp->IoStatus.Status = STATUS_CANCELLED;
1688}
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define STATUS_CANCELLED
Definition: udferr_usr.h:170

Referenced by MountMgrChangeNotify(), and MountMgrCleanup().

◆ MountMgrCreatePointWorker()

NTSTATUS MountMgrCreatePointWorker ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PUNICODE_STRING  SymbolicLinkName,
IN PUNICODE_STRING  DeviceName 
)

Definition at line 35 of file point.c.

38{
40 PLIST_ENTRY DeviceEntry;
41 PMOUNTDEV_UNIQUE_ID UniqueId;
42 PSYMLINK_INFORMATION SymlinkInformation;
43 UNICODE_STRING SymLink, TargetDeviceName;
44 PDEVICE_INFORMATION DeviceInformation = NULL, DeviceInfo;
45
46 /* Get device name */
48 &TargetDeviceName,
49 NULL, NULL, NULL,
50 NULL, NULL, NULL);
51 if (!NT_SUCCESS(Status))
52 {
53 return Status;
54 }
55
56 /* First of all, try to find device */
57 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
58 DeviceEntry != &(DeviceExtension->DeviceListHead);
59 DeviceEntry = DeviceEntry->Flink)
60 {
61 DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
62
63 if (RtlEqualUnicodeString(&TargetDeviceName, &(DeviceInformation->DeviceName), TRUE))
64 {
65 break;
66 }
67 }
68
69 /* Copy symbolic link name and null terminate it */
70 SymLink.Buffer = AllocatePool(SymbolicLinkName->Length + sizeof(UNICODE_NULL));
71 if (!SymLink.Buffer)
72 {
73 FreePool(TargetDeviceName.Buffer);
75 }
76
77 RtlCopyMemory(SymLink.Buffer, SymbolicLinkName->Buffer, SymbolicLinkName->Length);
78 SymLink.Buffer[SymbolicLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL;
79 SymLink.Length = SymbolicLinkName->Length;
80 SymLink.MaximumLength = SymbolicLinkName->Length + sizeof(UNICODE_NULL);
81
82 /* If we didn't find device */
83 if (DeviceEntry == &(DeviceExtension->DeviceListHead))
84 {
85 /* Then, try with unique ID */
87 NULL, &UniqueId,
88 NULL, NULL, NULL,
89 NULL, NULL);
90 if (!NT_SUCCESS(Status))
91 {
92 FreePool(TargetDeviceName.Buffer);
93 FreePool(SymLink.Buffer);
94 return Status;
95 }
96
97 /* Create a link to the device */
98 Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName);
99 if (!NT_SUCCESS(Status))
100 {
101 FreePool(UniqueId);
102 FreePool(TargetDeviceName.Buffer);
103 FreePool(SymLink.Buffer);
104 return Status;
105 }
106
107 /* If caller provided driver letter, delete it */
108 if (IsDriveLetter(&SymLink))
109 {
111 }
112
113 /* Device will be identified with its unique ID */
116 SymLink.Buffer,
118 UniqueId->UniqueId,
119 UniqueId->UniqueIdLength);
120
121 FreePool(UniqueId);
122 FreePool(TargetDeviceName.Buffer);
123 FreePool(SymLink.Buffer);
124 return Status;
125 }
126
127 /* If call provided a driver letter whereas device already has one
128 * fail, this is not doable
129 */
130 if (IsDriveLetter(&SymLink) && HasDriveLetter(DeviceInformation))
131 {
132 FreePool(TargetDeviceName.Buffer);
133 FreePool(SymLink.Buffer);
135 }
136
137 /* Now, create a link */
138 Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName);
139 FreePool(TargetDeviceName.Buffer);
140 if (!NT_SUCCESS(Status))
141 {
142 FreePool(SymLink.Buffer);
143 return Status;
144 }
145
146 /* Associate Unique ID <-> symbolic name */
147 UniqueId = DeviceInformation->UniqueId;
150 SymLink.Buffer,
152 UniqueId->UniqueId,
153 UniqueId->UniqueIdLength);
154 if (!NT_SUCCESS(Status))
155 {
156 GlobalDeleteSymbolicLink(&SymLink);
157 FreePool(SymLink.Buffer);
158 return Status;
159 }
160
161 /* Now, prepare to save the link with the device */
162 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
163 if (!SymlinkInformation)
164 {
166 GlobalDeleteSymbolicLink(&SymLink);
167 FreePool(SymLink.Buffer);
168 return Status;
169 }
170
171 SymlinkInformation->Name.Length = SymLink.Length;
172 SymlinkInformation->Name.MaximumLength = SymLink.Length + sizeof(UNICODE_NULL);
173 SymlinkInformation->Name.Buffer = AllocatePool(SymlinkInformation->Name.MaximumLength);
174 if (!SymlinkInformation->Name.Buffer)
175 {
177 FreePool(SymlinkInformation);
178 GlobalDeleteSymbolicLink(&SymLink);
179 FreePool(SymLink.Buffer);
180 return Status;
181 }
182
183 /* Save the link and mark it online */
184 RtlCopyMemory(SymlinkInformation->Name.Buffer, SymLink.Buffer, SymlinkInformation->Name.Length);
185 SymlinkInformation->Name.Buffer[SymlinkInformation->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
186 SymlinkInformation->Online = TRUE;
187 InsertTailList(&DeviceInformation->SymbolicLinksListHead, &SymlinkInformation->SymbolicLinksListEntry);
188 SendLinkCreated(&(SymlinkInformation->Name));
189
190 /* If we have a drive letter */
191 if (IsDriveLetter(&SymLink))
192 {
193 /* Then, delete the no drive letter entry */
194 DeleteNoDriveLetterEntry(UniqueId);
195
196 /* And post online notification if asked */
197 if (!DeviceInformation->SkipNotifications)
198 {
199 PostOnlineNotification(DeviceExtension, &DeviceInformation->SymbolicName);
200 }
201 }
202
203 /* If that's a volume with automatic drive letter, it's now time to resync databases */
204 if (MOUNTMGR_IS_VOLUME_NAME(&SymLink) && DeviceExtension->AutomaticDriveLetter)
205 {
206 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
207 DeviceEntry != &(DeviceExtension->DeviceListHead);
208 DeviceEntry = DeviceEntry->Flink)
209 {
210 DeviceInfo = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
211
212 /* If there's one, ofc! */
213 if (!DeviceInfo->NoDatabase)
214 {
216 }
217 }
218 }
219
220 /* Notify & quit */
221 FreePool(SymLink.Buffer);
222 MountMgrNotify(DeviceExtension);
223
224 if (!DeviceInformation->ManuallyRegistered)
225 {
226 MountMgrNotifyNameChange(DeviceExtension, DeviceName, FALSE);
227 }
228
229 return Status;
230}
VOID ReconcileThisDatabaseWithMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1613
VOID DeleteRegistryDriveLetter(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:2048
VOID DeleteNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:2100
#define InsertTailList(ListHead, Entry)
VOID SendLinkCreated(IN PUNICODE_STRING SymbolicName)
Definition: symlink.c:160
NTSTATUS GlobalCreateSymbolicLink(IN PUNICODE_STRING DosName, IN PUNICODE_STRING DeviceName)
Definition: symlink.c:111
NTSTATUS GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
Definition: symlink.c:136
NTSTATUS QueryDeviceInformation(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING DeviceName OPTIONAL, OUT PMOUNTDEV_UNIQUE_ID *UniqueId OPTIONAL, OUT PBOOLEAN Removable OPTIONAL, OUT PBOOLEAN GptDriveLetter OPTIONAL, OUT PBOOLEAN HasGuid OPTIONAL, IN OUT LPGUID StableGuid OPTIONAL, OUT PBOOLEAN Valid OPTIONAL)
Definition: mountmgr.c:190
VOID MountMgrNotifyNameChange(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN BOOLEAN ValidateVolume)
Definition: notify.c:351
VOID PostOnlineNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName)
Definition: notify.c:145
VOID MountMgrNotify(IN PDEVICE_EXTENSION DeviceExtension)
Definition: notify.c:311
BOOLEAN HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:83
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:61
BOOLEAN ManuallyRegistered
Definition: mntmgr.h:53
BOOLEAN SkipNotifications
Definition: mntmgr.h:58
UNICODE_STRING DeviceName
Definition: mntmgr.h:50
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING SymbolicLinkName
Definition: wdfdevice.h:3739

Referenced by MountMgrCreatePoint(), MountMgrNextDriveLetterWorker(), ProcessSuggestedDriveLetters(), and WriteUniqueIdToMaster().

◆ MountMgrFreeDeadDeviceInfo()

VOID MountMgrFreeDeadDeviceInfo ( IN PDEVICE_INFORMATION  DeviceInformation)

Definition at line 701 of file mountmgr.c.

702{
703 FreePool(DeviceInformation->SymbolicName.Buffer);
704 FreePool(DeviceInformation);
705}

Referenced by MountMgrCheckUnprocessedVolumes(), MountMgrMountedDeviceArrival(), MountMgrMountedDeviceRemoval(), and MountMgrUnload().

◆ MountMgrMountedDeviceArrival()

NTSTATUS MountMgrMountedDeviceArrival ( IN PDEVICE_EXTENSION  Extension,
IN PUNICODE_STRING  SymbolicName,
IN BOOLEAN  FromVolume 
)

Definition at line 931 of file mountmgr.c.

934{
936 GUID StableGuid;
937 HANDLE LinkHandle;
938 ULONG SymLinkCount, i;
939 PLIST_ENTRY NextEntry;
940 PUNICODE_STRING SymLinks;
941 NTSTATUS Status, IntStatus;
943 PSYMLINK_INFORMATION SymlinkInformation;
944 PMOUNTDEV_UNIQUE_ID UniqueId, NewUniqueId;
945 PSAVED_LINK_INFORMATION SavedLinkInformation;
946 PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
947 WCHAR CSymLinkBuffer[RTL_NUMBER_OF(Cunc)], LinkTargetBuffer[MAX_PATH];
948 UNICODE_STRING TargetDeviceName, SuggestedLinkName, DeviceName, VolumeName, DriveLetter, LinkTarget, CSymLink;
949 BOOLEAN HasGuid, HasGptDriveLetter, Valid, UseOnlyIfThereAreNoOtherLinks, IsDrvLetter, IsOff, IsVolumeName, LinkError;
950
951 /* New device = new structure to represent it */
952 DeviceInformation = AllocatePool(sizeof(DEVICE_INFORMATION));
953 if (!DeviceInformation)
954 {
956 }
957
958 /* Initialise device structure */
959 RtlZeroMemory(DeviceInformation, sizeof(DEVICE_INFORMATION));
960 InitializeListHead(&(DeviceInformation->SymbolicLinksListHead));
961 InitializeListHead(&(DeviceInformation->ReplicatedUniqueIdsListHead));
962 InitializeListHead(&(DeviceInformation->AssociatedDevicesHead));
963 DeviceInformation->SymbolicName.Length = SymbolicName->Length;
964 DeviceInformation->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(UNICODE_NULL);
965 DeviceInformation->SymbolicName.Buffer = AllocatePool(DeviceInformation->SymbolicName.MaximumLength);
966 if (!DeviceInformation->SymbolicName.Buffer)
967 {
968 FreePool(DeviceInformation);
970 }
971
972 /* Copy symbolic name */
974 DeviceInformation->SymbolicName.Buffer[DeviceInformation->SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
975 DeviceInformation->ManuallyRegistered = ManuallyRegistered;
976 DeviceInformation->DeviceExtension = DeviceExtension;
977
978 /* Query as much data as possible about device */
980 &TargetDeviceName,
981 &UniqueId,
982 &(DeviceInformation->Removable),
983 &HasGptDriveLetter,
984 &HasGuid,
985 &StableGuid,
986 &Valid);
987 if (!NT_SUCCESS(Status))
988 {
989 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
990
991 for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
992 NextEntry != &(DeviceExtension->OfflineDeviceListHead);
993 NextEntry = NextEntry->Flink)
994 {
995 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
996
997 if (RtlEqualUnicodeString(&(DeviceInformation->SymbolicName), &(CurrentDevice->SymbolicName), TRUE))
998 {
999 break;
1000 }
1001 }
1002
1003 if (NextEntry != &(DeviceExtension->OfflineDeviceListHead))
1004 {
1005 MountMgrFreeDeadDeviceInfo(DeviceInformation);
1006 }
1007 else
1008 {
1009 InsertTailList(&(DeviceExtension->OfflineDeviceListHead), &(DeviceInformation->DeviceListEntry));
1010 }
1011
1012 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1013
1014 return Status;
1015 }
1016
1017 /* Save gathered data */
1018 DeviceInformation->UniqueId = UniqueId;
1019 DeviceInformation->DeviceName = TargetDeviceName;
1020 DeviceInformation->KeepLinks = FALSE;
1021
1022 /* If we found system partition, mark it */
1023 if (DeviceExtension->DriveLetterData && UniqueId->UniqueIdLength == DeviceExtension->DriveLetterData->UniqueIdLength)
1024 {
1025 if (RtlCompareMemory(UniqueId->UniqueId, DeviceExtension->DriveLetterData->UniqueId, UniqueId->UniqueIdLength)
1026 == UniqueId->UniqueIdLength)
1027 {
1028 IoSetSystemPartition(&TargetDeviceName);
1029 }
1030 }
1031
1032 /* Check suggested link name */
1033 Status = QuerySuggestedLinkName(&(DeviceInformation->SymbolicName),
1034 &SuggestedLinkName,
1035 &UseOnlyIfThereAreNoOtherLinks);
1036 if (!NT_SUCCESS(Status))
1037 {
1038 SuggestedLinkName.Buffer = NULL;
1039 }
1040
1041 /* If it's OK, set it and save its letter (if any) */
1042 if (SuggestedLinkName.Buffer && IsDriveLetter(&SuggestedLinkName))
1043 {
1044 DeviceInformation->SuggestedDriveLetter = (UCHAR)SuggestedLinkName.Buffer[LETTER_POSITION];
1045 }
1046
1047 /* Acquire driver exclusively */
1048 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1049
1050 /* Check if we already have device in to prevent double registration */
1051 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1052 NextEntry != &(DeviceExtension->DeviceListHead);
1053 NextEntry = NextEntry->Flink)
1054 {
1055 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1056
1057 if (RtlEqualUnicodeString(&(CurrentDevice->DeviceName), &TargetDeviceName, TRUE))
1058 {
1059 break;
1060 }
1061 }
1062
1063 /* If we found it, clear ours, and return success, all correct */
1064 if (NextEntry != &(DeviceExtension->DeviceListHead))
1065 {
1066 if (SuggestedLinkName.Buffer)
1067 {
1068 FreePool(SuggestedLinkName.Buffer);
1069 }
1070
1071 FreePool(UniqueId);
1072 FreePool(TargetDeviceName.Buffer);
1073 FreePool(DeviceInformation->DeviceName.Buffer);
1074 FreePool(DeviceInformation);
1075
1076 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1077
1078 return STATUS_SUCCESS;
1079 }
1080
1081 /* Check if there are symlinks associated with our device in registry */
1082 Status = QuerySymbolicLinkNamesFromStorage(DeviceExtension,
1083 DeviceInformation,
1084 (SuggestedLinkName.Buffer) ? &SuggestedLinkName : NULL,
1085 UseOnlyIfThereAreNoOtherLinks,
1086 &SymLinks,
1087 &SymLinkCount,
1088 HasGuid,
1089 &StableGuid);
1090
1091 /* If our device is a CD-ROM */
1092 if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
1093 {
1094 LinkTarget.Length = 0;
1095 LinkTarget.MaximumLength = sizeof(LinkTargetBuffer);
1096 LinkTarget.Buffer = LinkTargetBuffer;
1097
1098 RtlCopyMemory(CSymLinkBuffer, Cunc, sizeof(Cunc));
1099 RtlInitUnicodeString(&CSymLink, CSymLinkBuffer);
1100
1101 /* Start checking all letters that could have been associated */
1102 for (Letter = L'D'; Letter <= L'Z'; Letter++)
1103 {
1105
1107 &CSymLink,
1109 NULL,
1110 NULL);
1111
1112 /* Try to open the associated symlink */
1114 if (!NT_SUCCESS(Status))
1115 {
1116 continue;
1117 }
1118
1119 /* And query its target */
1120 Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL);
1121 ZwClose(LinkHandle);
1122
1123 if (!NT_SUCCESS(Status))
1124 {
1125 continue;
1126 }
1127
1128 IntStatus = STATUS_UNSUCCESSFUL;
1129 if (!RtlEqualUnicodeString(&LinkTarget, &DeviceInformation->DeviceName, FALSE))
1130 {
1131 continue;
1132 }
1133
1134 /* This link is matching our device, whereas it's not supposed to have any
1135 * symlink associated.
1136 * Delete it
1137 */
1138 if (!SymLinkCount)
1139 {
1140 IoDeleteSymbolicLink(&CSymLink);
1141 continue;
1142 }
1143
1144 /* Now, for all the symlinks, check for ours */
1145 for (i = 0; i < SymLinkCount; i++)
1146 {
1147 if (IsDriveLetter(&(SymLinks[i])))
1148 {
1149 /* If it exists, that's correct */
1150 if (SymLinks[i].Buffer[LETTER_POSITION] == Letter)
1151 {
1152 IntStatus = STATUS_SUCCESS;
1153 }
1154 }
1155 }
1156
1157 /* Useless link, delete it */
1158 if (IntStatus == STATUS_UNSUCCESSFUL)
1159 {
1160 IoDeleteSymbolicLink(&CSymLink);
1161 }
1162 }
1163 }
1164
1165 /* Suggested name is no longer required */
1166 if (SuggestedLinkName.Buffer)
1167 {
1168 FreePool(SuggestedLinkName.Buffer);
1169 }
1170
1171 /* If if failed, ensure we don't take symlinks into account */
1172 if (!NT_SUCCESS(Status))
1173 {
1174 SymLinks = NULL;
1175 SymLinkCount = 0;
1176 }
1177
1178 /* Now we queried them, remove the symlinks */
1179 SavedLinkInformation = RemoveSavedLinks(DeviceExtension, UniqueId);
1180
1181 IsDrvLetter = FALSE;
1182 IsOff = FALSE;
1183 IsVolumeName = FALSE;
1184 /* For all the symlinks */
1185 for (i = 0; i < SymLinkCount; i++)
1186 {
1187 /* Check if our device is a volume */
1188 if (MOUNTMGR_IS_VOLUME_NAME(&(SymLinks[i])))
1189 {
1190 IsVolumeName = TRUE;
1191 }
1192 /* If it has a drive letter */
1193 else if (IsDriveLetter(&(SymLinks[i])))
1194 {
1195 if (IsDrvLetter)
1196 {
1197 DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1198 continue;
1199 }
1200 else
1201 {
1202 IsDrvLetter = TRUE;
1203 }
1204 }
1205
1206 /* And recreate the symlink to our device */
1207 Status = GlobalCreateSymbolicLink(&(SymLinks[i]), &TargetDeviceName);
1208 if (!NT_SUCCESS(Status))
1209 {
1210 LinkError = TRUE;
1211
1212 if ((SavedLinkInformation && !RedirectSavedLink(SavedLinkInformation, &(SymLinks[i]), &TargetDeviceName)) ||
1213 !SavedLinkInformation)
1214 {
1216 if (NT_SUCCESS(Status))
1217 {
1218 LinkError = RtlEqualUnicodeString(&TargetDeviceName, &DeviceName, TRUE);
1219 FreePool(DeviceName.Buffer);
1220 }
1221
1222 if (!LinkError)
1223 {
1224 if (IsDriveLetter(&(SymLinks[i])))
1225 {
1226 IsDrvLetter = FALSE;
1227 DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1228 }
1229
1230 FreePool(SymLinks[i].Buffer);
1231 continue;
1232 }
1233 }
1234 }
1235
1236 /* Check if was offline */
1237 if (IsOffline(&(SymLinks[i])))
1238 {
1239 IsOff = TRUE;
1240 }
1241
1242 /* Finally, associate this symlink with the device */
1243 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1244 if (!SymlinkInformation)
1245 {
1246 GlobalDeleteSymbolicLink(&(SymLinks[i]));
1247 FreePool(SymLinks[i].Buffer);
1248 continue;
1249 }
1250
1251 SymlinkInformation->Name = SymLinks[i];
1252 SymlinkInformation->Online = TRUE;
1253
1254 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1255 &(SymlinkInformation->SymbolicLinksListEntry));
1256 }
1257
1258 /* Now, for all the recreated symlinks, notify their recreation */
1259 for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1260 NextEntry != &(DeviceInformation->SymbolicLinksListHead);
1261 NextEntry = NextEntry->Flink)
1262 {
1263 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1264
1265 SendLinkCreated(&(SymlinkInformation->Name));
1266 }
1267
1268 /* If we had saved links, it's time to free them */
1269 if (SavedLinkInformation)
1270 {
1271 MountMgrFreeSavedLink(SavedLinkInformation);
1272 }
1273
1274 /* If our device doesn't have a volume name */
1275 if (!IsVolumeName)
1276 {
1277 /* It's time to create one */
1279 if (NT_SUCCESS(Status))
1280 {
1281 /* Write it to global database */
1285 REG_BINARY,
1286 UniqueId->UniqueId,
1287 UniqueId->UniqueIdLength);
1288
1289 /* And create the symlink */
1290 GlobalCreateSymbolicLink(&VolumeName, &TargetDeviceName);
1291
1292 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1293 if (!SymlinkInformation)
1294 {
1296 }
1297 /* Finally, associate it with the device and notify creation */
1298 else
1299 {
1300 SymlinkInformation->Name = VolumeName;
1301 SymlinkInformation->Online = TRUE;
1302 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1303 &(SymlinkInformation->SymbolicLinksListEntry));
1304
1306 }
1307 }
1308 }
1309
1310 /* If we found a drive letter, then, ignore the suggested one */
1311 if (IsDrvLetter)
1312 {
1313 DeviceInformation->SuggestedDriveLetter = 0;
1314 }
1315 /* Else, it's time to set up one */
1316 else if ((DeviceExtension->NoAutoMount || DeviceInformation->Removable) &&
1317 DeviceExtension->AutomaticDriveLetter &&
1318 (HasGptDriveLetter || DeviceInformation->SuggestedDriveLetter) &&
1319 !HasNoDriveLetterEntry(UniqueId))
1320 {
1321 /* Create a new drive letter */
1322 Status = CreateNewDriveLetterName(&DriveLetter, &TargetDeviceName,
1323 DeviceInformation->SuggestedDriveLetter,
1324 NULL);
1325 if (!NT_SUCCESS(Status))
1326 {
1327 CreateNoDriveLetterEntry(UniqueId);
1328 }
1329 else
1330 {
1331 /* Save it to global database */
1334 DriveLetter.Buffer,
1335 REG_BINARY,
1336 UniqueId->UniqueId,
1337 UniqueId->UniqueIdLength);
1338
1339 /* Associate it with the device and notify creation */
1340 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1341 if (!SymlinkInformation)
1342 {
1343 FreePool(DriveLetter.Buffer);
1344 }
1345 else
1346 {
1347 SymlinkInformation->Name = DriveLetter;
1348 SymlinkInformation->Online = TRUE;
1349 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1350 &(SymlinkInformation->SymbolicLinksListEntry));
1351
1352 SendLinkCreated(&DriveLetter);
1353 }
1354 }
1355 }
1356
1357 /* If that's a PnP device, register for notifications */
1358 if (!ManuallyRegistered)
1359 {
1360 RegisterForTargetDeviceNotification(DeviceExtension, DeviceInformation);
1361 }
1362
1363 /* Finally, insert the device into our devices list */
1364 InsertTailList(&(DeviceExtension->DeviceListHead), &(DeviceInformation->DeviceListEntry));
1365
1366 /* Copy device unique ID */
1367 NewUniqueId = AllocatePool(UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1368 if (NewUniqueId)
1369 {
1370 NewUniqueId->UniqueIdLength = UniqueId->UniqueIdLength;
1371 RtlCopyMemory(NewUniqueId->UniqueId, UniqueId->UniqueId, UniqueId->UniqueIdLength);
1372 }
1373
1374 /* If device's offline or valid, skip its notifications */
1375 if (IsOff || Valid)
1376 {
1377 DeviceInformation->SkipNotifications = TRUE;
1378 }
1379
1380 /* In case device is valid and is set to no automount,
1381 * set it offline.
1382 */
1383 if (DeviceExtension->NoAutoMount || IsDrvLetter)
1384 {
1385 IsOff = !DeviceInformation->SkipNotifications;
1386 }
1387 else
1388 {
1389 IsOff = FALSE;
1390 }
1391
1392 /* Finally, release the exclusive lock */
1393 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1394
1395 /* If device is not offline, notify its arrival */
1396 if (!IsOff)
1397 {
1399 }
1400
1401 /* If we had symlinks (from storage), free them */
1402 if (SymLinks)
1403 {
1404 FreePool(SymLinks);
1405 }
1406
1407 /* Notify about unique id change */
1408 if (NewUniqueId)
1409 {
1410 IssueUniqueIdChangeNotify(DeviceExtension, SymbolicName, NewUniqueId);
1411 FreePool(NewUniqueId);
1412 }
1413
1414 /* If this drive was set to have a drive letter automatically
1415 * Now it's back, local databases sync will be required
1416 */
1417 if (DeviceExtension->AutomaticDriveLetter)
1418 {
1419 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1420
1421 ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
1422
1423 NextEntry = DeviceExtension->DeviceListHead.Flink;
1424 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1425 while (CurrentDevice != DeviceInformation)
1426 {
1427 if (!CurrentDevice->NoDatabase)
1428 {
1429 ReconcileThisDatabaseWithMaster(DeviceExtension, CurrentDevice);
1430 }
1431
1432 NextEntry = NextEntry->Flink;
1433 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1434 }
1435
1436 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1437 }
1438
1439 return STATUS_SUCCESS;
1440}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define MAX_PATH
Definition: compat.h:34
VOID DeleteFromLocalDatabase(IN PUNICODE_STRING SymbolicLink, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: database.c:351
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
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 OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSTATUS QuerySymbolicLinkNamesFromStorage(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation, IN PUNICODE_STRING SuggestedLinkName, IN BOOLEAN UseOnlyIfThereAreNoOtherLinks, OUT PUNICODE_STRING *SymLinks, OUT PULONG SymLinkCount, IN BOOLEAN HasGuid, IN LPGUID Guid)
Definition: symlink.c:514
VOID SendOnlineNotification(IN PUNICODE_STRING SymbolicName)
Definition: notify.c:38
NTSTATUS CreateNewVolumeName(OUT PUNICODE_STRING VolumeName, IN PGUID VolumeGuid OPTIONAL)
Definition: symlink.c:462
UNICODE_STRING DeviceCdRom
Definition: symlink.c:35
VOID RegisterForTargetDeviceNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: notify.c:273
#define LETTER_POSITION
Definition: mntmgr.h:159
VOID IssueUniqueIdChangeNotify(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: notify.c:660
NTSTATUS QuerySuggestedLinkName(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING SuggestedLinkName, OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
Definition: symlink.c:684
PSAVED_LINK_INFORMATION RemoveSavedLinks(IN PDEVICE_EXTENSION DeviceExtension, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: symlink.c:640
VOID CreateNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:269
BOOLEAN HasNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: uniqueid.c:354
BOOLEAN RedirectSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation, IN PUNICODE_STRING DosName, IN PUNICODE_STRING NewLink)
Definition: symlink.c:827
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
BOOLEAN IsOffline(PUNICODE_STRING SymbolicName)
Definition: mountmgr.c:46
static const WCHAR Cunc[]
Definition: mountmgr.c:39
#define Cunc_LETTER_POSITION
Definition: mountmgr.c:40
NTSTATUS CreateNewDriveLetterName(OUT PUNICODE_STRING DriveLetter, IN PUNICODE_STRING DeviceName, IN UCHAR Letter, IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL)
Definition: mountmgr.c:108
VOID MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:701
VOID MountMgrFreeSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation)
Definition: mountmgr.c:766
NTSYSAPI NTSTATUS NTAPI ZwOpenSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
#define SYMBOLIC_LINK_QUERY
Definition: nt_native.h:1265
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS NTAPI IoSetSystemPartition(IN PUNICODE_STRING VolumeNameString)
Definition: volume.c:1226
BOOLEAN Removable
Definition: mntmgr.h:54
PDEVICE_EXTENSION DeviceExtension
Definition: mntmgr.h:62
BOOLEAN KeepLinks
Definition: mntmgr.h:51
BOOLEAN NoDatabase
Definition: mntmgr.h:57
UCHAR SuggestedDriveLetter
Definition: mntmgr.h:52
LIST_ENTRY ReplicatedUniqueIdsListHead
Definition: mntmgr.h:46
LIST_ENTRY AssociatedDevicesHead
Definition: mntmgr.h:47
LIST_ENTRY DeviceListEntry
Definition: mntmgr.h:44
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292

Referenced by MountMgrCheckUnprocessedVolumes(), MountMgrMountedDeviceNotification(), and MountMgrVolumeArrivalNotification().

◆ MountMgrMountedDeviceRemoval()

VOID MountMgrMountedDeviceRemoval ( IN PDEVICE_EXTENSION  Extension,
IN PUNICODE_STRING  DeviceName 
)

Definition at line 1446 of file mountmgr.c.

1448{
1449 PLIST_ENTRY NextEntry, DeviceEntry;
1450 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
1451 PSYMLINK_INFORMATION SymlinkInformation;
1453 PSAVED_LINK_INFORMATION SavedLinkInformation = NULL;
1454 PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
1455
1456 /* Acquire device exclusively */
1457 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1458
1459 /* Look for the leaving device */
1460 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1461 NextEntry != &(DeviceExtension->DeviceListHead);
1462 NextEntry = NextEntry->Flink)
1463 {
1464 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1465
1466 if (!RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE))
1467 {
1468 break;
1469 }
1470 }
1471
1472 /* If we found it */
1473 if (NextEntry != &(DeviceExtension->DeviceListHead))
1474 {
1475 /* If it's asked to keep links, then, prepare to save them */
1476 if (DeviceInformation->KeepLinks)
1477 {
1478 SavedLinkInformation = AllocatePool(sizeof(SAVED_LINK_INFORMATION));
1479 if (!SavedLinkInformation)
1480 {
1481 DeviceInformation->KeepLinks = FALSE;
1482 }
1483 }
1484
1485 /* If it's possible (and asked), start to save them */
1486 if (DeviceInformation->KeepLinks)
1487 {
1488 InsertTailList(&(DeviceExtension->SavedLinksListHead), &(SavedLinkInformation->SavedLinksListEntry));
1489 InitializeListHead(&(SavedLinkInformation->SymbolicLinksListHead));
1490 SavedLinkInformation->UniqueId = DeviceInformation->UniqueId;
1491 }
1492
1493 /* For all the symlinks */
1494 while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
1495 {
1496 NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
1497 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1498
1499 /* If we have to, save the link */
1500 if (DeviceInformation->KeepLinks)
1501 {
1502 InsertTailList(&(SavedLinkInformation->SymbolicLinksListHead), &(SymlinkInformation->SymbolicLinksListEntry));
1503 }
1504 /* Otherwise, just release it */
1505 else
1506 {
1507 GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
1508 FreePool(SymlinkInformation->Name.Buffer);
1509 FreePool(SymlinkInformation);
1510 }
1511 }
1512
1513 /* Free all the replicated unique IDs */
1514 while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
1515 {
1516 NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
1517 UniqueIdReplicate = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
1518
1519
1520 FreePool(UniqueIdReplicate->UniqueId);
1521 FreePool(UniqueIdReplicate);
1522 }
1523
1524 while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
1525 {
1526 NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
1527 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1528
1529 DeviceInformation->NoDatabase = TRUE;
1530 FreePool(AssociatedDevice->String.Buffer);
1532 }
1533
1534 /* Remove device from the device list */
1535 RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1536
1537 /* If there are still devices, check if some were associated with ours */
1538 if (!IsListEmpty(&(DeviceInformation->DeviceListEntry)))
1539 {
1540 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1541 NextEntry != &(DeviceExtension->DeviceListHead);
1542 NextEntry = NextEntry->Flink)
1543 {
1544 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1545
1546 /* And then, remove them */
1547 DeviceEntry = CurrentDevice->AssociatedDevicesHead.Flink;
1548 while (DeviceEntry != &(CurrentDevice->AssociatedDevicesHead))
1549 {
1550 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1551 DeviceEntry = DeviceEntry->Flink;
1552
1553 if (AssociatedDevice->DeviceInformation != DeviceInformation)
1554 {
1555 continue;
1556 }
1557
1558 RemoveEntryList(&(AssociatedDevice->AssociatedDevicesEntry));
1559 FreePool(AssociatedDevice->String.Buffer);
1561 }
1562 }
1563 }
1564
1565 /* Finally, clean up device name, symbolic name */
1566 FreePool(DeviceInformation->SymbolicName.Buffer);
1567 if (!DeviceInformation->KeepLinks)
1568 {
1569 FreePool(DeviceInformation->UniqueId);
1570 }
1571 FreePool(DeviceInformation->DeviceName.Buffer);
1572
1573 /* Unregister notifications */
1574 if (DeviceInformation->TargetDeviceNotificationEntry)
1575 {
1577 }
1578
1579 /* And leave */
1580 FreePool(DeviceInformation);
1581 }
1582 else
1583 {
1584 /* We didn't find device, perhaps because it was offline */
1585 for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
1586 NextEntry != &(DeviceExtension->OfflineDeviceListHead);
1587 NextEntry = NextEntry->Flink)
1588 {
1589 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1590
1591 /* It was, remove it */
1592 if (RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE) == 0)
1593 {
1594 RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1595 MountMgrFreeDeadDeviceInfo(DeviceInformation);
1596 break;
1597 }
1598 }
1599 }
1600
1601 /* Release driver */
1602 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1603}
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(_In_ PVOID NotificationEntry)
Definition: pnpnotify.c:479
Definition: mntmgr.h:96
PVOID TargetDeviceNotificationEntry
Definition: mntmgr.h:61
PMOUNTDEV_UNIQUE_ID UniqueId
Definition: mntmgr.h:82
_In_ WDFDEVICE AssociatedDevice
Definition: wdfinterrupt.h:173

Referenced by MountMgrMountedDeviceNotification().

◆ MountMgrNotify()

VOID MountMgrNotify ( IN PDEVICE_EXTENSION  DeviceExtension)

Definition at line 311 of file notify.c.

312{
313 PIRP Irp;
315 LIST_ENTRY CopyList;
316 PLIST_ENTRY NextEntry;
317
318 /* Increase the epic number */
319 DeviceExtension->EpicNumber++;
320
321 InitializeListHead(&CopyList);
322
323 /* Copy all the pending IRPs for notification */
325 while (!IsListEmpty(&(DeviceExtension->IrpListHead)))
326 {
327 NextEntry = RemoveHeadList(&(DeviceExtension->IrpListHead));
328 Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
330 InsertTailList(&CopyList, &(Irp->Tail.Overlay.ListEntry));
331 }
333
334 /* Then, notify them one by one */
335 while (!IsListEmpty(&CopyList))
336 {
337 NextEntry = RemoveHeadList(&CopyList);
338 Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
339
340 *((PULONG)Irp->AssociatedIrp.SystemBuffer) = DeviceExtension->EpicNumber;
341 Irp->IoStatus.Information = sizeof(DeviceExtension->EpicNumber);
342
344 }
345}
UCHAR KIRQL
Definition: env_spec_w32.h:591
IoSetCancelRoutine(Irp, CancelRoutine)
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
uint32_t * PULONG
Definition: typedefs.h:59
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by MountMgrCreatePointWorker(), MountMgrDeletePoints(), and MountMgrVolumeMountPointChanged().

◆ MountMgrNotifyNameChange()

VOID MountMgrNotifyNameChange ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PUNICODE_STRING  DeviceName,
IN BOOLEAN  ValidateVolume 
)

Definition at line 351 of file notify.c.

354{
355 PIRP Irp;
358 PLIST_ENTRY NextEntry;
363 PDEVICE_RELATIONS DeviceRelations;
364 PDEVICE_INFORMATION DeviceInformation;
365 TARGET_DEVICE_CUSTOM_NOTIFICATION DeviceNotification;
366
367 /* If we have to validate volume */
368 if (ValidateVolume)
369 {
370 /* Then, ensure we can find the device */
371 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
372 NextEntry != &DeviceExtension->DeviceListHead;
373 NextEntry = NextEntry->Flink)
374 {
375 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
376 if (RtlCompareUnicodeString(DeviceName, &(DeviceInformation->DeviceName), TRUE) == 0)
377 {
378 break;
379 }
380 }
381
382 /* No need to notify for a PnP device or if we didn't find the device */
383 if (NextEntry == &(DeviceExtension->DeviceListHead) ||
384 !DeviceInformation->ManuallyRegistered)
385 {
386 return;
387 }
388 }
389
390 /* Then, get device object */
393 &FileObject,
394 &DeviceObject);
395 if (!NT_SUCCESS(Status))
396 {
397 return;
398 }
399
401
403
404 /* Set up empty IRP (yes, yes!) */
407 NULL,
408 0,
409 NULL,
410 0,
411 FALSE,
412 &Event,
414 if (!Irp)
415 {
418 return;
419 }
420
422
423 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
424 Irp->IoStatus.Information = 0;
425
426 /* Properly set it, we want to query device relations */
427 Stack->MajorFunction = IRP_MJ_PNP;
428 Stack->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
429 Stack->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
430 Stack->FileObject = FileObject;
431
432 /* And call driver */
434 if (Status == STATUS_PENDING)
435 {
438 }
439
442
443 if (!NT_SUCCESS(Status))
444 {
445 return;
446 }
447
448 /* Validate device return */
450 if (DeviceRelations->Count < 1)
451 {
452 ExFreePool(DeviceRelations);
453 return;
454 }
455
456 DeviceObject = DeviceRelations->Objects[0];
457 ExFreePool(DeviceRelations);
458
459 /* Set up real notification */
460 DeviceNotification.Version = 1;
461 DeviceNotification.Size = sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION);
462 DeviceNotification.Event = GUID_IO_VOLUME_NAME_CHANGE;
463 DeviceNotification.FileObject = NULL;
464 DeviceNotification.NameBufferOffset = -1;
465
466 /* And report */
468 &DeviceNotification,
469 NULL, NULL);
470
472
473 return;
474}
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
if(dx< 0)
Definition: linetemp.h:194
@ NotificationEvent
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
NTSTATUS NTAPI IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject, IN PVOID NotificationStructure, IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, IN PVOID Context OPTIONAL)
Definition: pnpreport.c:498
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
struct _FILE_OBJECT * FileObject
Definition: iotypes.h:1012
@ TargetDeviceRelation
Definition: iotypes.h:2156
struct _DEVICE_RELATIONS * PDEVICE_RELATIONS
#define IRP_MN_QUERY_DEVICE_RELATIONS
struct _TARGET_DEVICE_CUSTOM_NOTIFICATION TARGET_DEVICE_CUSTOM_NOTIFICATION

Referenced by MountMgrCreatePointWorker(), MountMgrDeletePoints(), MountMgrQueryDosVolumePaths(), and MountMgrVolumeMountPointChanged().

◆ MountMgrQuerySymbolicLink()

NTSTATUS MountMgrQuerySymbolicLink ( IN PUNICODE_STRING  SymbolicName,
IN OUT PUNICODE_STRING  LinkTarget 
)

Definition at line 959 of file symlink.c.

961{
963 HANDLE LinkHandle;
965
966 /* Open the symbolic link */
970 NULL,
971 NULL);
972
973 Status = ZwOpenSymbolicLinkObject(&LinkHandle,
976 if (!NT_SUCCESS(Status))
977 {
978 return Status;
979 }
980
981 /* Query its target */
982 Status = ZwQuerySymbolicLinkObject(LinkHandle,
984 NULL);
985
986 ZwClose(LinkHandle);
987
988 if (!NT_SUCCESS(Status))
989 {
990 return Status;
991 }
992
993 if (LinkTarget->Length <= sizeof(WCHAR))
994 {
995 return Status;
996 }
997
998 /* If it's not finished by \, just return */
999 if (LinkTarget->Buffer[LinkTarget->Length / sizeof(WCHAR) - 1] != L'\\')
1000 {
1001 return Status;
1002 }
1003
1004 /* Otherwise, ensure to drop the tailing \ */
1005 LinkTarget->Length -= sizeof(WCHAR);
1007
1008 return Status;
1009}
#define GENERIC_READ
Definition: compat.h:135

Referenced by MountMgrVolumeMountPointCreated(), and MountMgrVolumeMountPointDeleted().

◆ MountmgrReadNoAutoMount()

BOOLEAN MountmgrReadNoAutoMount ( IN PUNICODE_STRING  RegistryPath)

Definition at line 898 of file mountmgr.c.

899{
901 ULONG Result, Default = 0;
903
905
906 /* Simply read data from register */
908 QueryTable[0].Name = L"NoAutoMount";
912 QueryTable[0].DefaultLength = sizeof(ULONG);
913
915 RegistryPath->Buffer,
917 NULL,
918 NULL);
919 if (!NT_SUCCESS(Status))
920 {
921 return (Default != 0);
922 }
923
924 return (Result != 0);
925}
@ Default
Definition: stdole2.idl:392
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define REG_NONE
Definition: nt_native.h:1492
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409

Referenced by DriverEntry().

◆ MountMgrUniqueIdChangeRoutine()

VOID MountMgrUniqueIdChangeRoutine ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PMOUNTDEV_UNIQUE_ID  OldUniqueId,
IN PMOUNTDEV_UNIQUE_ID  NewUniqueId 
)

Definition at line 71 of file uniqueid.c.

74{
76 BOOLEAN ResyncNeeded;
77 PUNIQUE_ID_REPLICATE DuplicateId;
78 PDEVICE_INFORMATION DeviceInformation;
80 PMOUNTDEV_UNIQUE_ID UniqueId, NewDuplicateId;
81 PLIST_ENTRY ListHead, NextEntry, ReplicatedHead, NextReplicated;
82
83 /* Synchronise with remote databases */
84 Status = WaitForRemoteDatabaseSemaphore(DeviceExtension);
85 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
86
89 QueryTable[0].EntryContext = NewUniqueId;
90
91 /* Write new data */
95 OldUniqueId,
96 NULL);
97
98 /* Browse all the devices to find the one that
99 * owns the old unique ID
100 */
101 ListHead = &(DeviceExtension->DeviceListHead);
102 NextEntry = ListHead->Flink;
103 while (ListHead != NextEntry)
104 {
105 DeviceInformation = CONTAINING_RECORD(NextEntry,
107 DeviceListEntry);
108
109 if (DeviceInformation->UniqueId->UniqueIdLength == OldUniqueId->UniqueIdLength &&
110 RtlCompareMemory(OldUniqueId->UniqueId,
111 DeviceInformation->UniqueId->UniqueId,
112 OldUniqueId->UniqueIdLength) == OldUniqueId->UniqueIdLength)
113 {
114 break;
115 }
116
117 NextEntry = NextEntry->Flink;
118 }
119
120 /* If we didn't find any release everything and quit */
121 if (ListHead == NextEntry)
122 {
123 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
124 1, FALSE);
125
126 if (NT_SUCCESS(Status))
127 {
128 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
129 }
130
131 return;
132 }
133
134 /* If lock failed, then, just update this database */
135 if (!NT_SUCCESS(Status))
136 {
137 ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
138 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
139 1, FALSE);
140 return;
141 }
142
143 /* Allocate new unique ID */
144 UniqueId = AllocatePool(NewUniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
145 if (!UniqueId)
146 {
147 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
148 1, FALSE);
149 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
150 return;
151 }
152
153 /* Release old one */
154 FreePool(DeviceInformation->UniqueId);
155 /* And set new one */
156 DeviceInformation->UniqueId = UniqueId;
157 UniqueId->UniqueIdLength = NewUniqueId->UniqueIdLength;
158 RtlCopyMemory(UniqueId->UniqueId, NewUniqueId->UniqueId, NewUniqueId->UniqueIdLength);
159
160 /* Now, check if it's required to update replicated unique IDs as well */
161 ListHead = &(DeviceExtension->DeviceListHead);
162 NextEntry = ListHead->Flink;
163 while (ListHead != NextEntry)
164 {
165 DeviceInformation = CONTAINING_RECORD(NextEntry,
167 DeviceListEntry);
168 ResyncNeeded = FALSE;
169
170 ReplicatedHead = &(DeviceInformation->ReplicatedUniqueIdsListHead);
171 NextReplicated = ReplicatedHead->Flink;
172 while (ReplicatedHead != NextReplicated)
173 {
174 DuplicateId = CONTAINING_RECORD(NextReplicated,
176 ReplicatedUniqueIdsListEntry);
177
178 if (DuplicateId->UniqueId->UniqueIdLength == OldUniqueId->UniqueIdLength)
179 {
180 if (RtlCompareMemory(DuplicateId->UniqueId->UniqueId,
181 OldUniqueId->UniqueId,
182 OldUniqueId->UniqueIdLength) == OldUniqueId->UniqueIdLength)
183 {
184 /* It was our old unique ID */
185 NewDuplicateId = AllocatePool(NewUniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
186 if (NewDuplicateId)
187 {
188 /* Update it */
189 ResyncNeeded = TRUE;
190 FreePool(DuplicateId->UniqueId);
191
192 DuplicateId->UniqueId = NewDuplicateId;
193 DuplicateId->UniqueId->UniqueIdLength = NewUniqueId->UniqueIdLength;
194 RtlCopyMemory(NewDuplicateId->UniqueId, NewUniqueId->UniqueId, NewUniqueId->UniqueIdLength);
195 }
196 }
197 }
198
199 NextReplicated = NextReplicated->Flink;
200 }
201
202 /* If resync is required on this device, do it */
203 if (ResyncNeeded)
204 {
205 ChangeRemoteDatabaseUniqueId(DeviceInformation, OldUniqueId, NewUniqueId);
206 }
207
208 NextEntry = NextEntry->Flink;
209 }
210
211 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
212 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
213
214 return;
215}
NTSTATUS WaitForRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:371
VOID ReleaseRemoteDatabaseSemaphore(IN PDEVICE_EXTENSION DeviceExtension)
Definition: database.c:391
VOID ChangeRemoteDatabaseUniqueId(IN PDEVICE_INFORMATION DeviceInformation, IN PMOUNTDEV_UNIQUE_ID OldUniqueId, IN PMOUNTDEV_UNIQUE_ID NewUniqueId)
Definition: database.c:1911
NTSTATUS NTAPI ChangeUniqueIdRoutine(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: uniqueid.c:36

Referenced by UniqueIdChangeNotifyWorker().

◆ 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}
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define DPRINT1
Definition: precomp.h:8
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
NTSTATUS CreateRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, IN OUT PHANDLE Database)
Definition: database.c:1790
UNICODE_STRING RemoteDatabase
Definition: database.c:34
#define FILE_OPEN
Definition: from_kernel.h:54
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
#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
#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
BOOLEAN NTAPI IoSetThreadHardErrorMode(IN BOOLEAN HardErrorEnabled)
Definition: error.c:726
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
#define IO_NO_PARAMETER_CHECKING
Definition: iotypes.h:541
@ CreateFileTypeNone
Definition: iotypes.h:535
#define IO_STOP_ON_SYMLINK
Definition: iotypes.h:7353
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103

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

◆ PostOnlineNotification()

VOID PostOnlineNotification ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PUNICODE_STRING  SymbolicName 
)

Definition at line 145 of file notify.c.

147{
150
151 /* Allocate a notification work item */
153 if (!WorkItem)
154 {
155 return;
156 }
157
159 WorkItem->DeviceExtension = DeviceExtension;
160 WorkItem->SymbolicName.Length = SymbolicName->Length;
161 WorkItem->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(WCHAR);
162 WorkItem->SymbolicName.Buffer = AllocatePool(WorkItem->SymbolicName.MaximumLength);
163 if (!WorkItem->SymbolicName.Buffer)
164 {
166 return;
167 }
168
170 WorkItem->SymbolicName.Buffer[SymbolicName->Length / sizeof(WCHAR)] = UNICODE_NULL;
171
172 KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
173 DeviceExtension->OnlineNotificationCount++;
174
175 /* If no worker are active */
176 if (DeviceExtension->OnlineNotificationWorkerActive == 0)
177 {
178 /* Queue that one for execution */
179 DeviceExtension->OnlineNotificationWorkerActive = 1;
181 }
182 else
183 {
184 /* Otherwise, just put it in the queue list */
185 InsertTailList(&(DeviceExtension->OnlineNotificationListHead), &(WorkItem->WorkItem.List));
186 }
187
188 KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
189
190 return;
191}
VOID NTAPI SendOnlineNotificationWorker(IN PVOID Parameter)
Definition: notify.c:96
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ DelayedWorkQueue
Definition: extypes.h:190

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

◆ QueryDeviceInformation()

NTSTATUS QueryDeviceInformation ( IN PUNICODE_STRING  SymbolicName,
OUT PUNICODE_STRING DeviceName  OPTIONAL,
OUT PMOUNTDEV_UNIQUE_ID *UniqueId  OPTIONAL,
OUT PBOOLEAN Removable  OPTIONAL,
OUT PBOOLEAN GptDriveLetter  OPTIONAL,
OUT PBOOLEAN HasGuid  OPTIONAL,
IN OUT LPGUID StableGuid  OPTIONAL,
OUT PBOOLEAN Valid  OPTIONAL 
)

Definition at line 190 of file mountmgr.c.

198{
199 PIRP Irp;
200 USHORT Size;
202 BOOLEAN IsRemovable;
207 NTSTATUS Status, IntStatus;
211 STORAGE_DEVICE_NUMBER StorageDeviceNumber;
213
214 /* Get device associated with the symbolic name */
217 &FileObject,
218 &DeviceObject);
219 if (!NT_SUCCESS(Status))
220 {
221 return Status;
222 }
223
224 /* The associate FO can't have a file name */
225 if (FileObject->FileName.Length)
226 {
229 }
230
231 /* Check if it's removable & return to the user (if asked to) */
232 IsRemovable = (FileObject->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA);
233 if (Removable)
234 {
235 *Removable = IsRemovable;
236 }
237
238 /* Get the attached device */
240
241 /* If we've been asked for a GPT drive letter */
242 if (GptDriveLetter)
243 {
244 /* Consider it has one */
245 *GptDriveLetter = TRUE;
246
247 if (!IsRemovable)
248 {
249 /* Query the GPT attributes */
253 NULL,
254 0,
255 &GptAttributes,
256 sizeof(GptAttributes),
257 FALSE,
258 &Event,
260 if (!Irp)
261 {
265 }
266
268 if (Status == STATUS_PENDING)
269 {
272 }
273
274 /* In case of failure, don't fail, that's no vital */
275 if (!NT_SUCCESS(Status))
276 {
278 }
279 /* Check if it has a drive letter */
280 else if (GptAttributes.GptAttributes & GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER)
281 {
282 *GptDriveLetter = FALSE;
283 }
284 }
285 }
286
287 /* If caller wants to know if there's valid contents */
288 if (Valid)
289 {
290 /* Suppose it's not OK */
291 *Valid = FALSE;
292
293 if (!IsRemovable)
294 {
295 /* Query partitions information */
299 NULL,
300 0,
302 sizeof(PartitionInfo),
303 FALSE,
304 &Event,
306 if (!Irp)
307 {
311 }
312
314 if (Status == STATUS_PENDING)
315 {
318 }
319
320 /* Once again here, failure isn't major */
321 if (!NT_SUCCESS(Status))
322 {
324 }
325 /* Verify we know something in */
326 else if (PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR &&
327 IsRecognizedPartition(PartitionInfo.Mbr.PartitionType))
328 {
329 *Valid = TRUE;
330 }
331
332 /* It looks correct, ensure it is & query device number */
333 if (*Valid)
334 {
338 NULL,
339 0,
340 &StorageDeviceNumber,
341 sizeof(StorageDeviceNumber),
342 FALSE,
343 &Event,
345 if (!Irp)
346 {
350 }
351
353 if (Status == STATUS_PENDING)
354 {
357 }
358
359 if (!NT_SUCCESS(Status))
360 {
362 }
363 else
364 {
365 *Valid = FALSE;
366 }
367 }
368 }
369 }
370
371 /* If caller needs device name */
372 if (DeviceName)
373 {
374 /* Allocate a buffer just to request length */
376 if (!Name)
377 {
381 }
382
383 /* Query device name */
387 NULL,
388 0,
389 Name,
390 sizeof(MOUNTDEV_NAME),
391 FALSE,
392 &Event,
394 if (!Irp)
395 {
396 FreePool(Name);
400 }
401
403 Stack->FileObject = FileObject;
404
406 if (Status == STATUS_PENDING)
407 {
410 }
411
412 /* Now, we've got the correct length */
414 {
415 Size = Name->NameLength + sizeof(MOUNTDEV_NAME);
416
417 FreePool(Name);
418
419 /* Allocate proper size */
421 if (!Name)
422 {
426 }
427
428 /* And query name (for real that time) */
432 NULL,
433 0,
434 Name,
435 Size,
436 FALSE,
437 &Event,
439 if (!Irp)
440 {
441 FreePool(Name);
445 }
446
448 Stack->FileObject = FileObject;
449
451 if (Status == STATUS_PENDING)
452 {
455 }
456 }
457
458 if (NT_SUCCESS(Status))
459 {
460 /* Copy back found name to the caller */
461 DeviceName->Length = Name->NameLength;
462 DeviceName->MaximumLength = Name->NameLength + sizeof(WCHAR);
463 DeviceName->Buffer = AllocatePool(DeviceName->MaximumLength);
464 if (!DeviceName->Buffer)
465 {
467 }
468 else
469 {
470 RtlCopyMemory(DeviceName->Buffer, Name->Name, Name->NameLength);
471 DeviceName->Buffer[Name->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
472 }
473 }
474
475 FreePool(Name);
476 }
477
478 if (!NT_SUCCESS(Status))
479 {
482 return Status;
483 }
484
485 /* If caller wants device unique ID */
486 if (UniqueId)
487 {
488 /* Prepare buffer to probe length */
490 if (!Id)
491 {
495 }
496
497 /* Query unique ID length */
501 NULL,
502 0,
503 Id,
504 sizeof(MOUNTDEV_UNIQUE_ID),
505 FALSE,
506 &Event,
508 if (!Irp)
509 {
510 FreePool(Id);
514 }
515
517 Stack->FileObject = FileObject;
518
520 if (Status == STATUS_PENDING)
521 {
524 }
525
526 /* Retry with appropriate length */
528 {
529 Size = Id->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID);
530
531 FreePool(Id);
532
533 /* Allocate the correct buffer */
535 if (!Id)
536 {
540 }
541
542 /* Query unique ID */
546 NULL,
547 0,
548 Id,
549 Size,
550 FALSE,
551 &Event,
553 if (!Irp)
554 {
555 FreePool(Id);
559 }
560
562 Stack->FileObject = FileObject;
563
565 if (Status == STATUS_PENDING)
566 {
569 }
570 }
571
572 /* Hands back unique ID */
573 if (NT_SUCCESS(Status))
574 {
575 *UniqueId = Id;
576 }
577 else
578 {
579 /* In case of failure, also free the rest */
580 FreePool(Id);
581 if (DeviceName->Length)
582 {
583 FreePool(DeviceName->Buffer);
584 }
585
588
589 return Status;
590 }
591 }
592
593 /* If user wants to know about GUID */
594 if (HasGuid)
595 {
596 /* Query device stable GUID */
600 NULL,
601 0,
602 StableGuid,
603 sizeof(GUID),
604 FALSE,
605 &Event,
607 if (!Irp)
608 {
612 }
613
615 Stack->FileObject = FileObject;
616
617 IntStatus = IoCallDriver(DeviceObject, Irp);
618 if (IntStatus == STATUS_PENDING)
619 {
621 IntStatus = IoStatusBlock.Status;
622 }
623
624 *HasGuid = NT_SUCCESS(IntStatus);
625 }
626
629 return Status;
630}
DWORD Id
struct NameRec_ * Name
Definition: cdprocs.h:460
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
struct _MOUNTDEV_NAME MOUNTDEV_NAME
struct _MOUNTDEV_UNIQUE_ID MOUNTDEV_UNIQUE_ID
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID
Definition: imports.h:255
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:342
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_VOLUME_GET_GPT_ATTRIBUTES
Definition: ntddvol.h:56
@ Removable
Definition: arc.h:81
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105

Referenced by FindDeviceInfo(), MountMgrCreatePointWorker(), MountMgrMountedDeviceArrival(), MountMgrNextDriveLetterWorker(), MountMgrVolumeMountPointChanged(), MountMgrVolumeMountPointCreated(), QueryPointsFromMemory(), QueryPointsFromSymbolicLinkName(), USBD_GetDeviceInformationEx(), and USBH_GetDeviceType().

◆ QueryPointsFromMemory()

NTSTATUS QueryPointsFromMemory ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PIRP  Irp,
IN PMOUNTDEV_UNIQUE_ID UniqueId  OPTIONAL,
IN PUNICODE_STRING SymbolicName  OPTIONAL 
)

Definition at line 236 of file point.c.

240{
244 PMOUNTMGR_MOUNT_POINTS MountPoints;
245 PDEVICE_INFORMATION DeviceInformation;
246 PLIST_ENTRY DeviceEntry, SymlinksEntry;
247 PSYMLINK_INFORMATION SymlinkInformation;
248 USHORT UniqueIdLength, DeviceNameLength;
249 ULONG TotalSize, TotalSymLinks, UniqueIdOffset, DeviceNameOffset;
250
251 /* If we got a symbolic link, query device */
252 if (SymbolicName)
253 {
255 &DeviceName,
256 NULL, NULL,
257 NULL, NULL,
258 NULL, NULL);
259 if (!NT_SUCCESS(Status))
260 {
261 return Status;
262 }
263 }
264
265 /* Browse all the links to count number of links & size used */
266 TotalSize = 0;
267 TotalSymLinks = 0;
268 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
269 DeviceEntry != &(DeviceExtension->DeviceListHead);
270 DeviceEntry = DeviceEntry->Flink)
271 {
272 DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
273
274 /* If we were given an unique ID, it has to match */
275 if (UniqueId)
276 {
277 if (UniqueId->UniqueIdLength != DeviceInformation->UniqueId->UniqueIdLength)
278 {
279 continue;
280 }
281
282 if (RtlCompareMemory(UniqueId->UniqueId,
283 DeviceInformation->UniqueId->UniqueId,
284 UniqueId->UniqueIdLength) != UniqueId->UniqueIdLength)
285 {
286 continue;
287 }
288 }
289 /* Or, if we had a symlink, it has to match */
290 else if (SymbolicName)
291 {
292 if (!RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE))
293 {
294 continue;
295 }
296 }
297
298 /* Once here, it matched, save device name & unique ID size */
299 TotalSize += DeviceInformation->DeviceName.Length + DeviceInformation->UniqueId->UniqueIdLength;
300
301 /* And count number of symlinks (and their size) */
302 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
303 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
304 SymlinksEntry = SymlinksEntry->Flink)
305 {
306 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
307
308 TotalSize += SymlinkInformation->Name.Length;
309 TotalSymLinks++;
310 }
311
312 /* We had a specific item to find
313 * if we reach that point, we found it, no need to continue
314 */
315 if (UniqueId || SymbolicName)
316 {
317 break;
318 }
319 }
320
321 /* If we were looking for specific item, ensure we found it */
322 if (UniqueId || SymbolicName)
323 {
324 if (DeviceEntry == &(DeviceExtension->DeviceListHead))
325 {
326 if (SymbolicName)
327 {
328 FreePool(DeviceName.Buffer);
329 }
330
332 }
333 }
334
335 /* Now, ensure output buffer can hold everything */
337 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
338 RtlZeroMemory(MountPoints, Stack->Parameters.DeviceIoControl.OutputBufferLength);
339
340 /* Ensure we set output to let user reallocate! */
341 MountPoints->Size = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalSymLinks * sizeof(MOUNTMGR_MOUNT_POINT) + TotalSize;
342 MountPoints->NumberOfMountPoints = TotalSymLinks;
343 Irp->IoStatus.Information = MountPoints->Size;
344
345 if (MountPoints->Size > Stack->Parameters.DeviceIoControl.OutputBufferLength)
346 {
347 Irp->IoStatus.Information = sizeof(MOUNTMGR_MOUNT_POINTS);
348
349 if (SymbolicName)
350 {
351 FreePool(DeviceName.Buffer);
352 }
353
355 }
356
357 /* Now, start putting mount points */
358 TotalSize = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalSymLinks * sizeof(MOUNTMGR_MOUNT_POINT);
359 TotalSymLinks = 0;
360 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
361 DeviceEntry != &(DeviceExtension->DeviceListHead);
362 DeviceEntry = DeviceEntry->Flink)
363 {
364 DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
365
366 /* Find back correct mount point */
367 if (UniqueId)
368 {
369 if (UniqueId->UniqueIdLength != DeviceInformation->UniqueId->UniqueIdLength)
370 {
371 continue;
372 }
373
374 if (RtlCompareMemory(UniqueId->UniqueId,
375 DeviceInformation->UniqueId->UniqueId,
376 UniqueId->UniqueIdLength) != UniqueId->UniqueIdLength)
377 {
378 continue;
379 }
380 }
381 else if (SymbolicName)
382 {
383 if (!RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE))
384 {
385 continue;
386 }
387 }
388
389 /* Save our information about shared data */
390 UniqueIdOffset = TotalSize;
391 UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength;
392 DeviceNameOffset = TotalSize + UniqueIdLength;
393 DeviceNameLength = DeviceInformation->DeviceName.Length;
394
395 /* Initialize first symlink */
396 MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset = UniqueIdOffset;
397 MountPoints->MountPoints[TotalSymLinks].UniqueIdLength = UniqueIdLength;
398 MountPoints->MountPoints[TotalSymLinks].DeviceNameOffset = DeviceNameOffset;
399 MountPoints->MountPoints[TotalSymLinks].DeviceNameLength = DeviceNameLength;
400
401 /* And copy data */
402 RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + UniqueIdOffset),
403 DeviceInformation->UniqueId->UniqueId, UniqueIdLength);
404 RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + DeviceNameOffset),
405 DeviceInformation->DeviceName.Buffer, DeviceNameLength);
406
407 TotalSize += DeviceInformation->UniqueId->UniqueIdLength + DeviceInformation->DeviceName.Length;
408
409 /* Now we've got it, but all the data */
410 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
411 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
412 SymlinksEntry = SymlinksEntry->Flink)
413 {
414 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
415
416 /* First, set shared data */
417
418 /* Only put UniqueID if online */
419 if (SymlinkInformation->Online)
420 {
421 MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset = UniqueIdOffset;
422 MountPoints->MountPoints[TotalSymLinks].UniqueIdLength = UniqueIdLength;
423 }
424 else
425 {
426 MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset = 0;
427 MountPoints->MountPoints[TotalSymLinks].UniqueIdLength = 0;
428 }
429
430 MountPoints->MountPoints[TotalSymLinks].DeviceNameOffset = DeviceNameOffset;
431 MountPoints->MountPoints[TotalSymLinks].DeviceNameLength = DeviceNameLength;
432
433 /* And now, copy specific symlink info */
434 MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameOffset = TotalSize;
435 MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameLength = SymlinkInformation->Name.Length;
436
437 RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameOffset),
438 SymlinkInformation->Name.Buffer, SymlinkInformation->Name.Length);
439
440 /* Update counters */
441 TotalSymLinks++;
442 TotalSize += SymlinkInformation->Name.Length;
443 }
444
445 if (UniqueId || SymbolicName)
446 {
447 break;
448 }
449 }
450
451 if (SymbolicName)
452 {
453 FreePool(DeviceName.Buffer);
454 }
455
456 return STATUS_SUCCESS;
457}
struct _MOUNTMGR_MOUNT_POINTS * PMOUNTMGR_MOUNT_POINTS
struct _MOUNTMGR_MOUNT_POINTS MOUNTMGR_MOUNT_POINTS
MOUNTMGR_MOUNT_POINT MountPoints[1]
Definition: imports.h:177
USHORT DeviceNameLength
Definition: imports.h:171
USHORT SymbolicLinkNameLength
Definition: imports.h:167
ULONG SymbolicLinkNameOffset
Definition: imports.h:166
uint16_t * PWSTR
Definition: typedefs.h:56
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793

Referenced by MountMgrQueryPoints().

◆ QueryPointsFromSymbolicLinkName()

NTSTATUS QueryPointsFromSymbolicLinkName ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PUNICODE_STRING  SymbolicName,
IN PIRP  Irp 
)

Definition at line 463 of file point.c.

466{
471 PMOUNTMGR_MOUNT_POINTS MountPoints;
472 PDEVICE_INFORMATION DeviceInformation = NULL;
473 PLIST_ENTRY DeviceEntry, SymlinksEntry;
474 PSYMLINK_INFORMATION SymlinkInformation;
475
476 /* Find device */
478 NULL, NULL, NULL,
479 NULL, NULL, NULL);
480 if (NT_SUCCESS(Status))
481 {
482 /* Look for the device information */
483 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
484 DeviceEntry != &(DeviceExtension->DeviceListHead);
485 DeviceEntry = DeviceEntry->Flink)
486 {
487 DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
488
489 if (RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE))
490 {
491 break;
492 }
493 }
494
495 FreePool(DeviceName.Buffer);
496
497 if (DeviceEntry == &(DeviceExtension->DeviceListHead))
498 {
500 }
501
502 /* Check for the link */
503 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
504 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
505 SymlinksEntry = SymlinksEntry->Flink)
506 {
507 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
508
509 if (RtlEqualUnicodeString(SymbolicName, &SymlinkInformation->Name, TRUE))
510 {
511 break;
512 }
513 }
514
515 if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead))
516 {
518 }
519 }
520 else
521 {
522 /* Browse all the devices to try to find the one
523 * that has the given link...
524 */
525 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
526 DeviceEntry != &(DeviceExtension->DeviceListHead);
527 DeviceEntry = DeviceEntry->Flink)
528 {
529 DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
530
531 for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
532 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
533 SymlinksEntry = SymlinksEntry->Flink)
534 {
535 SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
536
537 if (RtlEqualUnicodeString(SymbolicName, &SymlinkInformation->Name, TRUE))
538 {
539 break;
540 }
541 }
542
543 if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
544 {
545 break;
546 }
547 }
548
549 /* Even that way we didn't find, give up! */
550 if (DeviceEntry == &(DeviceExtension->DeviceListHead))
551 {
553 }
554 }
555
556 /* Get output buffer */
558 MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
559
560 /* Compute output length */
561 TotalLength = DeviceInformation->UniqueId->UniqueIdLength +
562 SymlinkInformation->Name.Length + DeviceInformation->DeviceName.Length;
563
564 /* Give length to allow reallocation */
565 MountPoints->Size = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalLength;
566 MountPoints->NumberOfMountPoints = 1;
567 Irp->IoStatus.Information = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalLength;
568
569 if (MountPoints->Size > Stack->Parameters.DeviceIoControl.OutputBufferLength)
570 {
571 Irp->IoStatus.Information = sizeof(MOUNTMGR_MOUNT_POINTS);
572
574 }
575
576 /* Write out data */
578 MountPoints->MountPoints[0].SymbolicLinkNameLength = SymlinkInformation->Name.Length;
579 /* If link is online write it's unique ID, otherwise, forget about it */
580 if (SymlinkInformation->Online)
581 {
582 MountPoints->MountPoints[0].UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
583 SymlinkInformation->Name.Length;
584 MountPoints->MountPoints[0].UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength;
585 }
586 else
587 {
588 MountPoints->MountPoints[0].UniqueIdOffset = 0;
589 MountPoints->MountPoints[0].UniqueIdLength = 0;
590 }
591
592 MountPoints->MountPoints[0].DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
593 SymlinkInformation->Name.Length +
594 DeviceInformation->UniqueId->UniqueIdLength;
595 MountPoints->MountPoints[0].DeviceNameLength = DeviceInformation->DeviceName.Length;
596
597 RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].SymbolicLinkNameOffset),
598 SymlinkInformation->Name.Buffer, SymlinkInformation->Name.Length);
599
600 if (SymlinkInformation->Online)
601 {
602 RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].UniqueIdOffset),
603 DeviceInformation->UniqueId->UniqueId, DeviceInformation->UniqueId->UniqueIdLength);
604 }
605
606 RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].DeviceNameOffset),
607 DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);
608
609 return STATUS_SUCCESS;
610}
#define ULONG_PTR
Definition: config.h:101
_In_ ULONG TotalLength
Definition: usbdlib.h:158

Referenced by MountMgrQueryPoints().

◆ QuerySuggestedLinkName()

NTSTATUS QuerySuggestedLinkName ( IN PUNICODE_STRING  SymbolicName,
OUT PUNICODE_STRING  SuggestedLinkName,
OUT PBOOLEAN  UseOnlyIfThereAreNoOtherLinks 
)

Definition at line 684 of file symlink.c.

687{
688 PIRP Irp;
691 USHORT NameLength;
695 PIO_STACK_LOCATION IoStackLocation;
696 PMOUNTDEV_SUGGESTED_LINK_NAME IoCtlSuggested;
697
698 /* First, get device */
701 &FileObject,
702 &DeviceObject);
703 if (!NT_SUCCESS(Status))
704 {
705 return Status;
706 }
707
708 /* Then, get attached device */
710
711 /* Then, prepare buffer to query suggested name */
712 IoCtlSuggested = AllocatePool(sizeof(MOUNTDEV_SUGGESTED_LINK_NAME));
713 if (!IoCtlSuggested)
714 {
716 goto Dereference;
717 }
718
719 /* Prepare request */
723 NULL,
724 0,
725 IoCtlSuggested,
727 FALSE,
728 &Event,
730 if (!Irp)
731 {
733 goto Release;
734 }
735
736 IoStackLocation = IoGetNextIrpStackLocation(Irp);
737 IoStackLocation->FileObject = FileObject;
738
739 /* And ask */
741 if (Status == STATUS_PENDING)
742 {
744 FALSE, NULL);
746 }
747
748 /* Overflow? Normal */
750 {
751 /* Reallocate big enough buffer */
752 NameLength = IoCtlSuggested->NameLength + sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
753 FreePool(IoCtlSuggested);
754
755 IoCtlSuggested = AllocatePool(NameLength);
756 if (!IoCtlSuggested)
757 {
759 goto Dereference;
760 }
761
762 /* And reask */
766 NULL,
767 0,
768 IoCtlSuggested,
769 NameLength,
770 FALSE,
771 &Event,
773 if (!Irp)
774 {
776 goto Release;
777 }
778
779 IoStackLocation = IoGetNextIrpStackLocation(Irp);
780 IoStackLocation->FileObject = FileObject;
781
783 if (Status == STATUS_PENDING)
784 {
786 FALSE, NULL);
788 }
789 }
790
791 if (!NT_SUCCESS(Status))
792 {
793 goto Release;
794 }
795
796 /* Now we have suggested name, copy it */
797 SuggestedLinkName->Length = IoCtlSuggested->NameLength;
798 SuggestedLinkName->MaximumLength = IoCtlSuggested->NameLength + sizeof(UNICODE_NULL);
799 SuggestedLinkName->Buffer = AllocatePool(IoCtlSuggested->NameLength + sizeof(UNICODE_NULL));
800 if (!SuggestedLinkName->Buffer)
801 {
803 }
804 else
805 {
806 RtlCopyMemory(SuggestedLinkName->Buffer, IoCtlSuggested->Name, IoCtlSuggested->NameLength);
807 SuggestedLinkName->Buffer[SuggestedLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL;
808 }
809
810 /* Also return its priority */
811 *UseOnlyIfThereAreNoOtherLinks = IoCtlSuggested->UseOnlyIfThereAreNoOtherLinks;
812
813Release:
814 FreePool(IoCtlSuggested);
815
816Dereference:
819
820 return Status;
821}
_In_ BOOLEAN Release
Definition: cdrom.h:920
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
struct _MOUNTDEV_SUGGESTED_LINK_NAME MOUNTDEV_SUGGESTED_LINK_NAME
PFILE_OBJECT FileObject
Definition: iotypes.h:3169

Referenced by MountMgrMountedDeviceArrival().

◆ QuerySymbolicLinkNamesFromStorage()

NTSTATUS QuerySymbolicLinkNamesFromStorage ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PDEVICE_INFORMATION  DeviceInformation,
IN PUNICODE_STRING  SuggestedLinkName,
IN BOOLEAN  UseOnlyIfThereAreNoOtherLinks,
OUT PUNICODE_STRING SymLinks,
OUT PULONG  SymLinkCount,
IN BOOLEAN  HasGuid,
IN LPGUID  Guid 
)

Definition at line 514 of file symlink.c.

522{
524 BOOLEAN WriteNew;
526
527 UNREFERENCED_PARAMETER(DeviceExtension);
528
529 /* First of all, count links */
532 QueryTable[0].EntryContext = SymLinkCount;
533 *SymLinkCount = 0;
534
538 DeviceInformation->UniqueId,
539 NULL);
540 if (!NT_SUCCESS(Status))
541 {
542 *SymLinkCount = 0;
543 }
544
545 /* Check if we have to write a new one first */
546 if (SuggestedLinkName && !IsDriveLetter(SuggestedLinkName) &&
547 UseOnlyIfThereAreNoOtherLinks && *SymLinkCount == 0)
548 {
549 WriteNew = TRUE;
550 }
551 else
552 {
553 WriteNew = FALSE;
554 }
555
556 /* If has GUID, it makes one more link */
557 if (HasGuid)
558 {
559 (*SymLinkCount)++;
560 }
561
562 if (WriteNew)
563 {
564 /* Write link */
567 SuggestedLinkName->Buffer,
569 DeviceInformation->UniqueId->UniqueId,
570 DeviceInformation->UniqueId->UniqueIdLength);
571
572 /* And recount all the needed links */
575 QueryTable[0].EntryContext = SymLinkCount;
576 *SymLinkCount = 0;
577
581 DeviceInformation->UniqueId,
582 NULL);
583 if (!NT_SUCCESS(Status))
584 {
585 return STATUS_NOT_FOUND;
586 }
587 }
588
589 /* Not links found? */
590 if (!*SymLinkCount)
591 {
592 return STATUS_NOT_FOUND;
593 }
594
595 /* Allocate a buffer big enough to hold symlinks (table of unicode strings) */
596 *SymLinks = AllocatePool(*SymLinkCount * sizeof(UNICODE_STRING));
597 if (!*SymLinks)
598 {
600 }
601
602 /* Prepare to query links */
603 RtlZeroMemory(*SymLinks, *SymLinkCount * sizeof(UNICODE_STRING));
606
607 /* No GUID? Keep it that way */
608 if (!HasGuid)
609 {
610 QueryTable[0].EntryContext = *SymLinks;
611 }
612 /* Otherwise, first create volume name */
613 else
614 {
615 Status = CreateNewVolumeName(SymLinks[0], Guid);
616 if (!NT_SUCCESS(Status))
617 {
618 FreePool(*SymLinks);
619 return Status;
620 }
621
622 /* Skip first link (ours) */
623 QueryTable[0].EntryContext = *SymLinks + 1;
624 }
625
626 /* Now, query */
630 DeviceInformation->UniqueId,
631 NULL);
632
633 return STATUS_SUCCESS;
634}
#define STATUS_NOT_FOUND
Definition: shellext.h:72

Referenced by MountMgrMountedDeviceArrival().

◆ 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_SHARE_READ
Definition: compat.h:136
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
@ FileNameInformation
Definition: from_kernel.h:70
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
ULONG Handle
Definition: gdb_input.c:15
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_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:97
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
struct _REPARSE_DATA_BUFFER::@318::@321 MountPointReparseBuffer
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE
Definition: iotypes.h:7213

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

◆ 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}

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 there's no automount, and automatic letters
1645 * all volumes to find those online and notify there presence
1646 */
1647 if (DeviceExtension->WorkerThreadStatus == 0 &&
1648 DeviceExtension->AutomaticDriveLetter == 1 &&
1649 DeviceExtension->NoAutoMount == FALSE)
1650 {
1651 OnlineMountedVolumes(DeviceExtension, DeviceInformation);
1652 }
1653}
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}
WCHAR FileNameBuffer[MAX_PATH]
Definition: framewnd.c:233
NTSTATUS QueryUniqueIdFromMaster(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, OUT PMOUNTDEV_UNIQUE_ID *UniqueId)
Definition: database.c:440
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
NTSTATUS QueryVolumeName(IN HANDLE RootDirectory, IN PFILE_REPARSE_POINT_INFORMATION ReparsePointInformation, IN PUNICODE_STRING FileName OPTIONAL, OUT PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING VolumeName)
Definition: database.c:1292
#define DO_UNLOAD_PENDING
Definition: env_spec_w32.h:392
struct _FileName FileName
Definition: fatprocs.h:896
@ FileReparsePointInformation
Definition: from_kernel.h:94
@ Unloading
Definition: fs_rec.h:188
#define InterlockedExchangeAdd
Definition: interlocked.h:181
struct _RECONCILE_WORK_ITEM_CONTEXT * PRECONCILE_WORK_ITEM_CONTEXT
UNICODE_STRING ReparseIndex
Definition: symlink.c:40
NTSTATUS FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
Definition: mountmgr.c:636
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
#define FILE_GENERIC_READ
Definition: nt_native.h:653
@ Restart
Definition: sacdrv.h:269
BOOLEAN NeedsReconcile
Definition: mntmgr.h:56
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323

Referenced by MountMgrQueryDosVolumePaths(), and ReconcileThisDatabaseWithMaster().

◆ RedirectSavedLink()

BOOLEAN RedirectSavedLink ( IN PSAVED_LINK_INFORMATION  SavedLinkInformation,
IN PUNICODE_STRING  DosName,
IN PUNICODE_STRING  NewLink 
)

Definition at line 827 of file symlink.c.

830{
831 PLIST_ENTRY NextEntry;
832 PSYMLINK_INFORMATION SymlinkInformation;
833
834 /* Find the link */
835 for (NextEntry = SavedLinkInformation->SymbolicLinksListHead.Flink;
836 NextEntry != &(SavedLinkInformation->SymbolicLinksListHead);
837 NextEntry = NextEntry->Flink)
838 {
839 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
840
841 if (!RtlEqualUnicodeString(DosName, &(SymlinkInformation->Name), TRUE))
842 {
843 /* Delete old link */
845 /* Set its new location */
847
848 /* And remove it from the list (not valid any more) */
849 RemoveEntryList(&(SymlinkInformation->SymbolicLinksListEntry));
850 FreePool(SymlinkInformation->Name.Buffer);
851 FreePool(SymlinkInformation);
852
853 return TRUE;
854 }
855 }
856
857 return FALSE;
858}

Referenced by MountMgrMountedDeviceArrival().

◆ RegisterForTargetDeviceNotification()

VOID RegisterForTargetDeviceNotification ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PDEVICE_INFORMATION  DeviceInformation 
)

Definition at line 273 of file notify.c.

275{
279
280 /* Get device object */
281 Status = IoGetDeviceObjectPointer(&(DeviceInformation->DeviceName),
283 &FileObject,
284 &DeviceObject);
285 if (!NT_SUCCESS(Status))
286 {
287 return;
288 }
289
290 /* And simply register for notifications */
292 0, FileObject,
293 DeviceExtension->DriverObject,
295 DeviceInformation,
296 &(DeviceInformation->TargetDeviceNotificationEntry));
297 if (!NT_SUCCESS(Status))
298 {
299 DeviceInformation->TargetDeviceNotificationEntry = NULL;
300 }
301
303
304 return;
305}
NTSTATUS NTAPI MountMgrTargetDeviceNotification(IN PVOID NotificationStructure, IN PVOID Context)
Definition: notify.c:229
NTSTATUS NTAPI IoRegisterPlugPlayNotification(_In_ IO_NOTIFICATION_EVENT_CATEGORY EventCategory, _In_ ULONG EventCategoryFlags, _In_opt_ PVOID EventCategoryData, _In_ PDRIVER_OBJECT DriverObject, _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, _Inout_opt_ PVOID Context, _Out_ PVOID *NotificationEntry)
Definition: pnpnotify.c:345
@ EventCategoryTargetDeviceChange
Definition: iotypes.h:1227

Referenced by MountMgrMountedDeviceArrival().

◆ 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().

◆ RemoveSavedLinks()

PSAVED_LINK_INFORMATION RemoveSavedLinks ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PMOUNTDEV_UNIQUE_ID  UniqueId 
)

Definition at line 640 of file symlink.c.

642{
643 PLIST_ENTRY NextEntry;
644 PSAVED_LINK_INFORMATION SavedLinkInformation;
645
646 /* No saved links? Easy! */
647 if (IsListEmpty(&(DeviceExtension->SavedLinksListHead)))
648 {
649 return NULL;
650 }
651
652 /* Now, browse saved links */
653 for (NextEntry = DeviceExtension->SavedLinksListHead.Flink;
654 NextEntry != &(DeviceExtension->SavedLinksListHead);
655 NextEntry = NextEntry->Flink)
656 {
657 SavedLinkInformation = CONTAINING_RECORD(NextEntry,
659 SavedLinksListEntry);
660
661 /* Find the one that matches */
662 if (SavedLinkInformation->UniqueId->UniqueIdLength == UniqueId->UniqueIdLength)
663 {
664 if (RtlCompareMemory(SavedLinkInformation->UniqueId->UniqueId,
665 UniqueId->UniqueId,
666 UniqueId->UniqueIdLength) ==
667 UniqueId->UniqueIdLength)
668 {
669 /* Remove it and return it */
670 RemoveEntryList(&(SavedLinkInformation->SavedLinksListEntry));
671 return SavedLinkInformation;
672 }
673 }
674 }
675
676 /* None found (none removed) */
677 return NULL;
678}

Referenced by MountMgrMountedDeviceArrival().

◆ SendLinkCreated()

VOID SendLinkCreated ( IN PUNICODE_STRING  SymbolicName)

Definition at line 160 of file symlink.c.

161{
162 PIRP Irp;
164 ULONG NameSize;
171
172 /* Get the device associated with the name */
175 &FileObject,
176 &DeviceObject);
177 if (!NT_SUCCESS(Status))
178 {
179 return;
180 }
181
182 /* Get attached device (will notify it) */
184
185 /* NameSize is the size of the whole MOUNTDEV_NAME struct */
186 NameSize = sizeof(USHORT) + SymbolicName->Length;
187 Name = AllocatePool(NameSize);
188 if (!Name)
189 {
190 goto Cleanup;
191 }
192
193 /* Initialize struct */
194 Name->NameLength = SymbolicName->Length;
196
198 /* Microsoft does it twice... Once with limited access, second with any
199 * So, first one here
200 */
203 Name,
204 NameSize,
205 NULL,
206 0,
207 FALSE,
208 &Event,
210 /* This one can fail, no one matters */
211 if (Irp)
212 {
214 Stack->FileObject = FileObject;
215
217 if (Status == STATUS_PENDING)
218 {
220 }
221 }
222
223 /* Then, second one */
227 Name,
228 NameSize,
229 NULL,
230 0,
231 FALSE,
232 &Event,
234 if (!Irp)
235 {
236 goto Cleanup;
237 }
238
240 Stack->FileObject = FileObject;
241
242 /* Really notify */
244 if (Status == STATUS_PENDING)
245 {
247 }
248
249Cleanup:
250 if (Name)
251 {
252 FreePool(Name);
253 }
254
257
258 return;
259}
#define IOCTL_MOUNTDEV_LINK_CREATED
Definition: imports.h:106
#define MOUNTDEVCONTROLTYPE
Definition: imports.h:78
#define CTL_CODE(DeviceType, Function, Method, Access)
Definition: nt_native.h:586
#define FILE_WRITE_ACCESS
Definition: nt_native.h:611
#define METHOD_BUFFERED
Definition: nt_native.h:594
#define FILE_READ_ACCESS
Definition: nt_native.h:610

Referenced by MountMgrCreatePointWorker(), and MountMgrMountedDeviceArrival().

◆ SendOnlineNotification()

VOID SendOnlineNotification ( IN PUNICODE_STRING  SymbolicName)

Definition at line 38 of file notify.c.

39{
40 PIRP Irp;
47
48 /* Get device object */
53 if (!NT_SUCCESS(Status))
54 {
55 return;
56 }
57
58 /* And attached device object */
60
61 /* And send VOLUME_ONLINE */
65 NULL, 0,
66 NULL, 0,
67 FALSE,
68 &Event,
70 if (!Irp)
71 {
72 goto Cleanup;
73 }
74
76 Stack->FileObject = FileObject;
77
80 {
82 }
83
87
88 return;
89}
#define IOCTL_VOLUME_ONLINE
Definition: ntddvol.h:62

Referenced by MountMgrMountedDeviceArrival(), and SendOnlineNotificationWorker().

◆ UpdateReplicatedUniqueIds()

VOID UpdateReplicatedUniqueIds ( IN PDEVICE_INFORMATION  DeviceInformation,
IN PDATABASE_ENTRY  DatabaseEntry 
)

Definition at line 376 of file uniqueid.c.

377{
378 PLIST_ENTRY NextEntry;
379 PUNIQUE_ID_REPLICATE ReplicatedUniqueId, NewEntry;
380
381 /* Browse all the device replicated unique IDs */
382 for (NextEntry = DeviceInformation->ReplicatedUniqueIdsListHead.Flink;
383 NextEntry != &(DeviceInformation->ReplicatedUniqueIdsListHead);
384 NextEntry = NextEntry->Flink)
385 {
386 ReplicatedUniqueId = CONTAINING_RECORD(NextEntry,
388 ReplicatedUniqueIdsListEntry);
389
390 if (ReplicatedUniqueId->UniqueId->UniqueIdLength != DatabaseEntry->UniqueIdLength)
391 {
392 continue;
393 }
394
395 /* If we find the UniqueId to update, break */
396 if (RtlCompareMemory(ReplicatedUniqueId->UniqueId->UniqueId,
397 (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
398 ReplicatedUniqueId->UniqueId->UniqueIdLength) == ReplicatedUniqueId->UniqueId->UniqueIdLength)
399 {
400 break;
401 }
402 }
403
404 /* We found the unique ID, no need to continue */
405 if (NextEntry != &(DeviceInformation->ReplicatedUniqueIdsListHead))
406 {
407 return;
408 }
409
410 /* Allocate a new entry for unique ID */
411 NewEntry = AllocatePool(sizeof(UNIQUE_ID_REPLICATE));
412 if (!NewEntry)
413 {
414 return;
415 }
416
417 /* Allocate the unique ID */
418 NewEntry->UniqueId = AllocatePool(DatabaseEntry->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
419 if (!NewEntry->UniqueId)
420 {
421 FreePool(NewEntry);
422 return;
423 }
424
425 /* Copy */
426 NewEntry->UniqueId->UniqueIdLength = DatabaseEntry->UniqueIdLength;
428 (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
429 DatabaseEntry->UniqueIdLength);
430 /* And insert into replicated unique IDs list */
431 InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &NewEntry->ReplicatedUniqueIdsListEntry);
432
433 return;
434}
LIST_ENTRY ReplicatedUniqueIdsListEntry
Definition: mntmgr.h:81

Referenced by ReconcileThisDatabaseWithMasterWorker().

◆ WaitForOnlinesToComplete()

VOID WaitForOnlinesToComplete ( IN PDEVICE_EXTENSION  DeviceExtension)

Definition at line 197 of file notify.c.

198{
200
201 KeInitializeEvent(&(DeviceExtension->OnlineNotificationEvent), NotificationEvent, FALSE);
202
203 KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
204
205 /* Just wait all the worker are done */
206 if (DeviceExtension->OnlineNotificationCount != 1)
207 {
208 DeviceExtension->OnlineNotificationCount--;
209 KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
210
211 KeWaitForSingleObject(&(DeviceExtension->OnlineNotificationEvent),
212 Executive,
214 FALSE,
215 NULL);
216
217 KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
218 DeviceExtension->OnlineNotificationCount++;
219 }
220
221 KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
222}

Referenced by MountMgrDeviceControl().

◆ 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().

◆ 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().

Variable Documentation

◆ DatabasePath

◆ DeviceCdRom

UNICODE_STRING DeviceCdRom
extern

◆ DeviceFloppy

UNICODE_STRING DeviceFloppy
extern

Definition at line 34 of file symlink.c.

Referenced by CreateNewDriveLetterName(), and MountMgrNextDriveLetterWorker().

◆ DeviceMount

UNICODE_STRING DeviceMount
extern

Definition at line 31 of file symlink.c.

Referenced by DriverEntry().

◆ DosDevices

◆ DosDevicesMount

UNICODE_STRING DosDevicesMount
extern

Definition at line 32 of file symlink.c.

Referenced by DriverEntry(), and MountMgrUnload().

◆ DosGlobal

UNICODE_STRING DosGlobal
extern

Definition at line 36 of file symlink.c.

Referenced by CreateStringWithGlobal().

◆ DriverEntry

DRIVER_INITIALIZE DriverEntry

Definition at line 180 of file mntmgr.h.

◆ gdeviceObject

PDEVICE_OBJECT gdeviceObject
extern

Definition at line 35 of file mountmgr.c.

Referenced by DriverEntry(), and MountMgrUnload().

◆ Global

◆ MountMgrDeviceControl

DRIVER_DISPATCH MountMgrDeviceControl

Definition at line 340 of file mntmgr.h.

Referenced by DriverEntry().

◆ OfflinePath

PWSTR OfflinePath
extern

Definition at line 32 of file database.c.

Referenced by IsOffline().

◆ ReparseIndex

UNICODE_STRING ReparseIndex
extern

Definition at line 40 of file symlink.c.

Referenced by OnlineMountedVolumes(), and ReconcileThisDatabaseWithMasterWorker().

◆ SafeVolumes

UNICODE_STRING SafeVolumes
extern

Definition at line 38 of file symlink.c.

Referenced by WorkerThread().

◆ UnloadEvent

KEVENT UnloadEvent
extern

Definition at line 36 of file mountmgr.c.

Referenced by MountMgrShutdown(), MountMgrUnload(), and WorkerThread().

◆ Unloading

LONG Unloading
extern

Definition at line 37 of file mountmgr.c.

Referenced by MountMgrShutdown(), and MountMgrUnload().

◆ Volume

_In_ PFLT_VOLUME Volume
extern

Definition at line 1172 of file fltkernel.h.

Referenced by auxMessage(), BroadcastDriveLetterChange(), CreateNewVolumeName(), DismountMain(), Ext2CopyDoubleIndirectBlockPointers(), Ext2CopyIndirectBlockPointers(), Ext2CopyTripleIndirectBlockPointers(), Ext2GetInodeBlockNumber(), Ext2GetInodeGroupNumber(), Ext2GetInodeOffsetInBlock(), Ext2LookupFile(), Ext2Mount(), Ext2Open(), Ext2OpenFile(), Ext2OpenVolume(), Ext2ReadBlock(), Ext2ReadBlockPointerList(), Ext2ReadDirectory(), Ext2ReadFileBig(), Ext2ReadGroupDescriptor(), Ext2ReadGroupDescriptors(), Ext2ReadInode(), Ext2ReadPartialBlock(), Ext2ReadSuperBlock(), Ext2ReadVolumeSectors(), FatBufferDirectory(), FatCountClustersInChain(), FatGetFatEntry(), FatGetFatSector(), FatLookupFile(), FatMount(), FatOpenVolume(), FatReadAdjacentClusters(), FatReadClusterChain(), FatReadFile(), FatReadPartialCluster(), FatReadVolumeSectors(), FatSeek(), FilterInstanceSetup(), FltEnumerateVolumes(), FltGetDiskDeviceObject(), FltGetVolumeName(), FltGetVolumeProperties(), LockOrUnlockVolume(), MMixerGetChannelCountLegacy(), NtfsDiskRead(), NtfsFindAttribute(), NtfsFindAttributeHelper(), NtfsFindMftRecord(), NtfsFixupRecord(), NtfsInfoMain(), NtfsLookupFile(), NtfsMount(), NtfsOpen(), NtfsReadAttribute(), NtfsReadMftRecord(), OpenVolume(), PopFlushVolumes(), PopFlushVolumeWorker(), QueryMain(), RawMountVolume(), SetMain(), CAC97MiniportTopology::SetMultichannelVolume(), SmpCreatePagingFileOnAnyDrive(), SmpCreatePagingFileOnFixedDrive(), SmpCreateVolumeDescriptors(), SmpGetVolumeFreeSpace(), SmpSearchVolumeDescriptor(), and StatisticsMain().