ReactOS 0.4.16-dev-287-g2d3f3a1
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

 _IRQL_requires_ (PASSIVE_LEVEL) NTSTATUS MountMgrSendSyncDeviceIoCtl(_In_ ULONG IoControlCode
 
_In_ PDEVICE_OBJECT _In_reads_bytes_opt_ (InputBufferLength) PVOID InputBuffer
 
_In_ PDEVICE_OBJECT _In_ ULONG _Out_writes_bytes_opt_ (OutputBufferLength) PVOID OutputBuffer
 
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_opt_ PUNICODE_STRING DeviceName, _Out_opt_ PMOUNTDEV_UNIQUE_ID *UniqueId, _Out_opt_ PBOOLEAN Removable, _Out_opt_ PBOOLEAN GptDriveLetter, _Out_opt_ PBOOLEAN HasGuid, _Inout_opt_ LPGUID StableGuid, _Out_opt_ PBOOLEAN IsFT)
 
BOOLEAN HasDriveLetter (IN PDEVICE_INFORMATION DeviceInformation)
 
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
 
_In_ PDEVICE_OBJECT DeviceObject
 
_In_ PDEVICE_OBJECT _In_ ULONG InputBufferLength
 
_In_ PDEVICE_OBJECT _In_ ULONG _In_ ULONG OutputBufferLength
 
_In_ PDEVICE_OBJECT _In_ ULONG _In_ ULONG _In_opt_ PFILE_OBJECT FileObject
 
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

◆ _In_reads_bytes_opt_()

_In_ PDEVICE_OBJECT _In_reads_bytes_opt_ ( InputBufferLength  )

◆ _IRQL_requires_()

_IRQL_requires_ ( PASSIVE_LEVEL  )

Definition at line 2121 of file class.c.

13175{
13177
13178 PAGED_CODE();
13179
13180 TracePrint((TRACE_LEVEL_VERBOSE,
13181 TRACE_FLAG_PNP,
13182 "ClassDetermineTokenOperationCommandSupport (%p): Entering function.\n",
13183 DeviceObject));
13184
13185 //
13186 // Send down Inquiry for VPD_THIRD_PARTY_COPY_PAGE and cache away the device parameters
13187 // from WINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR.
13188 //
13190
13191 if (NT_SUCCESS(status)) {
13192
13193 ULONG maxListIdentifier = MaxTokenOperationListIdentifier;
13194
13195 //
13196 // Query the maximum list identifier to use for TokenOperation commands.
13197 //
13198 if (NT_SUCCESS(ClasspGetMaximumTokenListIdentifier(DeviceObject, REG_DISK_CLASS_CONTROL, &maxListIdentifier))) {
13199 if (maxListIdentifier >= MIN_TOKEN_LIST_IDENTIFIERS) {
13200
13201 NT_ASSERT(maxListIdentifier <= MAX_TOKEN_LIST_IDENTIFIERS);
13202 MaxTokenOperationListIdentifier = maxListIdentifier;
13203 }
13204 }
13205
13206 }
13207
13208 TracePrint((TRACE_LEVEL_VERBOSE,
13209 TRACE_FLAG_PNP,
13210 "ClassDetermineTokenOperationCommandSupport (%p): Exiting function with status %x.\n",
13212 status));
13213
13214 return status;
13215}
#define PAGED_CODE()
LONG NTSTATUS
Definition: precomp.h:26
#define REG_DISK_CLASS_CONTROL
Definition: classp.h:218
#define MAX_TOKEN_LIST_IDENTIFIERS
Definition: classp.h:215
#define MIN_TOKEN_LIST_IDENTIFIERS
Definition: classp.h:214
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
ULONG MaxTokenOperationListIdentifier
Definition: class.c:107
_IRQL_requires_same_ NTSTATUS ClasspGetBlockDeviceTokenLimitsInfo(_Inout_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:13220
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
Definition: ps.c:97
uint32_t ULONG
Definition: typedefs.h:59
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define NT_ASSERT
Definition: rtlfuncs.h:3327

◆ _Out_writes_bytes_opt_()

_In_ PDEVICE_OBJECT _In_ ULONG _Out_writes_bytes_opt_ ( OutputBufferLength  )

◆ 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}
#define FALSE
Definition: types.h:117
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
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 399 of file symlink.c.

401{
402 GUID Guid;
405
406 /* If no GUID was provided, then create one */
407 if (!VolumeGuid)
408 {
410 if (!NT_SUCCESS(Status))
411 {
412 return Status;
413 }
414 }
415 else
416 {
417 RtlCopyMemory(&Guid, VolumeGuid, sizeof(GUID));
418 }
419
420 /* Convert GUID to string */
422 if (!NT_SUCCESS(Status))
423 {
424 return Status;
425 }
426
427 /* Size for volume namespace, literal GUID, and null char */
428 VolumeName->MaximumLength = 0x14 + 0x4C + sizeof(UNICODE_NULL);
429 VolumeName->Buffer = AllocatePool(0x14 + 0x4C + sizeof(UNICODE_NULL));
430 if (!VolumeName->Buffer)
431 {
433 }
434 else
435 {
440 }
441
442 ExFreePoolWithTag(GuidString.Buffer, 0);
443
444 return Status;
445}
_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:4220
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
#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 754 of file symlink.c.

757{
758 PLIST_ENTRY DeviceEntry, SymbolEntry;
759 PDEVICE_INFORMATION DeviceInformation;
760 PSYMLINK_INFORMATION SymlinkInformation;
761
762 /* First of all, ensure we have devices */
763 if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
764 {
765 return;
766 }
767
768 /* Then, look for the symbolic name */
769 for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
770 DeviceEntry != &(DeviceExtension->DeviceListHead);
771 DeviceEntry = DeviceEntry->Flink)
772 {
773 DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
774
775 for (SymbolEntry = DeviceInformation->SymbolicLinksListHead.Flink;
776 SymbolEntry != &(DeviceInformation->SymbolicLinksListHead);
777 SymbolEntry = SymbolEntry->Flink)
778 {
779 SymlinkInformation = CONTAINING_RECORD(SymbolEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
780
781 /* One we have found it */
782 if (RtlCompareUnicodeString(SymbolicLink, &(SymlinkInformation->Name), TRUE) == 0)
783 {
784 /* Check if caller just want it to be offline */
785 if (MarkOffline)
786 {
787 SymlinkInformation->Online = FALSE;
788 }
789 else
790 {
791 /* If not, delete it & notify */
792 SendLinkDeleted(&(DeviceInformation->SymbolicName), SymbolicLink);
793 RemoveEntryList(&(SymlinkInformation->SymbolicLinksListEntry));
794
795 FreePool(SymlinkInformation->Name.Buffer);
796 FreePool(SymlinkInformation);
797 }
798
799 /* No need to go farther */
800 return;
801 }
802 }
803 }
804
805 return;
806}
#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 561 of file mountmgr.c.

565{
567 PLIST_ENTRY NextEntry;
570
571 /* If a device name was given, use it */
572 if (DeviceNameGiven)
573 {
576 }
577 else
578 {
579 /* Otherwise, query it */
581 &DeviceName,
582 NULL, NULL,
583 NULL, NULL,
584 NULL, NULL);
585 if (!NT_SUCCESS(Status))
586 {
587 return Status;
588 }
589 }
590
591 /* Look for device information matching devive */
592 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
593 NextEntry != &(DeviceExtension->DeviceListHead);
594 NextEntry = NextEntry->Flink)
595 {
596 DeviceInfo = CONTAINING_RECORD(NextEntry,
598 DeviceListEntry);
599
600 if (RtlEqualUnicodeString(&DeviceName, &(DeviceInfo->DeviceName), TRUE))
601 {
602 break;
603 }
604 }
605
606 /* Release our buffer if required */
607 if (!DeviceNameGiven)
608 {
609 FreePool(DeviceName.Buffer);
610 }
611
612 /* Return found information */
613 if (NextEntry == &(DeviceExtension->DeviceListHead))
614 {
616 }
617
618 *DeviceInformation = DeviceInfo;
619 return STATUS_SUCCESS;
620}
NTSTATUS QueryDeviceInformation(_In_ PUNICODE_STRING SymbolicName, _Out_opt_ PUNICODE_STRING DeviceName, _Out_opt_ PMOUNTDEV_UNIQUE_ID *UniqueId, _Out_opt_ PBOOLEAN Removable, _Out_opt_ PBOOLEAN GptDriveLetter, _Out_opt_ PBOOLEAN HasGuid, _Inout_opt_ LPGUID StableGuid, _Out_opt_ PBOOLEAN IsFT)
Definition: mountmgr.c:274
_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:732
_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 120 of file symlink.c.

122{
124 UNICODE_STRING GlobalName;
125
126 /* First create the global string */
127 Status = CreateStringWithGlobal(DosName, &GlobalName);
128 if (!NT_SUCCESS(Status))
129 {
130 return Status;
131 }
132
133 /* Then, create the symlink */
134 Status = IoCreateSymbolicLink(&GlobalName, DeviceName);
135
136 FreePool(GlobalName.Buffer);
137
138 return Status;
139}
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1286

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

◆ GlobalDeleteSymbolicLink()

NTSTATUS GlobalDeleteSymbolicLink ( IN PUNICODE_STRING  DosName)

Definition at line 145 of file symlink.c.

146{
148 UNICODE_STRING GlobalName;
149
150 /* Recreate the string (to find the link) */
151 Status = CreateStringWithGlobal(DosName, &GlobalName);
152 if (!NT_SUCCESS(Status))
153 {
154 return Status;
155 }
156
157 /* And delete the link */
158 Status = IoDeleteSymbolicLink(&GlobalName);
159
160 FreePool(GlobalName.Buffer);
161
162 return Status;
163}

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

◆ HasDriveLetter()

BOOLEAN HasDriveLetter ( IN PDEVICE_INFORMATION  DeviceInformation)

Definition at line 167 of file mountmgr.c.

168{
169 PLIST_ENTRY NextEntry;
170 PSYMLINK_INFORMATION SymlinkInfo;
171
172 /* Browse all the symlinks to check if there is at least a drive letter */
173 for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
174 NextEntry != &DeviceInformation->SymbolicLinksListHead;
175 NextEntry = NextEntry->Flink)
176 {
177 SymlinkInfo = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
178
179 if (IsDriveLetter(&SymlinkInfo->Name) && SymlinkInfo->Online)
180 {
181 return TRUE;
182 }
183 }
184
185 return FALSE;
186}
BOOLEAN IsDriveLetter(PUNICODE_STRING SymbolicName)
Definition: symlink.c:812

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 812 of file symlink.c.

813{
815
816 /* We must have a precise length */
817 if (SymbolicName->Length != DosDevices.Length + 2 * sizeof(WCHAR))
818 {
819 return FALSE;
820 }
821
822 /* Must start with the DosDevices prefix */
824 {
825 return FALSE;
826 }
827
828 /* Check if letter is correct */
830 if ((Letter < L'A' || Letter > L'Z') && Letter != (WCHAR)-1)
831 {
832 return FALSE;
833 }
834
835 /* And finally it must end with a colon */
837 if (Colon != L':')
838 {
839 return FALSE;
840 }
841
842 return TRUE;
843}
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 637 of file notify.c.

640{
642 PVOID IrpBuffer = NULL;
646
647 /* Get the associated device object */
650 &FileObject,
651 &DeviceObject);
652 if (!NT_SUCCESS(Status))
653 {
654 return;
655 }
656
657 /* And then, get attached device */
659
661
662 /* Allocate a work item */
664 if (!WorkItem)
665 {
667 return;
668 }
669
670 WorkItem->Event = NULL;
671 WorkItem->WorkItem = IoAllocateWorkItem(DeviceExtension->DeviceObject);
672 if (!WorkItem->WorkItem)
673 {
675 goto Cleanup;
676 }
677
678 WorkItem->DeviceExtension = DeviceExtension;
679 WorkItem->StackSize = DeviceObject->StackSize;
680 /* Already provide the IRP */
681 WorkItem->Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
682
684
685 if (!WorkItem->Irp)
686 {
687 goto Cleanup;
688 }
689
690 /* Ensure it has enough space */
691 IrpBuffer = AllocatePool(sizeof(MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT) + 1024);
692 if (!IrpBuffer)
693 {
694 goto Cleanup;
695 }
696
697 WorkItem->DeviceName.Length = DeviceName->Length;
698 WorkItem->DeviceName.MaximumLength = DeviceName->Length + sizeof(WCHAR);
699 WorkItem->DeviceName.Buffer = AllocatePool(WorkItem->DeviceName.MaximumLength);
700 if (!WorkItem->DeviceName.Buffer)
701 {
702 goto Cleanup;
703 }
704
705 RtlCopyMemory(WorkItem->DeviceName.Buffer, DeviceName->Buffer, DeviceName->Length);
706 WorkItem->DeviceName.Buffer[DeviceName->Length / sizeof(WCHAR)] = UNICODE_NULL;
707
708 WorkItem->IrpBuffer = IrpBuffer;
709 WorkItem->IrpBufferLength = sizeof(MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT) + 1024;
710
711 /* Add the worker in the list */
712 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
713 InsertHeadList(&(DeviceExtension->UniqueIdWorkerItemListHead), &(WorkItem->UniqueIdWorkerItemListEntry));
714 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
715
716 /* And call the worker */
718
719 return;
720
721Cleanup:
722 if (IrpBuffer)
723 {
724 FreePool(IrpBuffer);
725 }
726
727 if (WorkItem->Irp)
728 {
729 IoFreeIrp(WorkItem->Irp);
730 }
731
732 if (WorkItem->WorkItem)
733 {
734 IoFreeWorkItem(WorkItem->WorkItem);
735 }
736
737 if (WorkItem)
738 {
740 }
741}
static const WCHAR Cleanup[]
Definition: register.c:80
VOID IssueUniqueIdChangeNotifyWorker(IN PUNIQUE_ID_WORK_ITEM WorkItem, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: notify.c:567
#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_ 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 567 of file notify.c.

569{
570 PIRP Irp;
575
576 /* Get the device object */
579 &FileObject,
580 &DeviceObject);
581 if (!NT_SUCCESS(Status))
582 {
584 return;
585 }
586
587 /* And then, the attached device */
589
590 /* Initialize the IRP */
591 Irp = WorkItem->Irp;
592 IoInitializeIrp(Irp, IoSizeOfIrp(WorkItem->StackSize), (CCHAR)WorkItem->StackSize);
593
594 if (InterlockedExchange((PLONG)&(WorkItem->Event), 0) != 0)
595 {
599 return;
600 }
601
602 Irp->AssociatedIrp.SystemBuffer = WorkItem->IrpBuffer;
603 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
604 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, UniqueId, UniqueId->UniqueIdLength + sizeof(USHORT));
605
607
608 Stack->Parameters.DeviceIoControl.InputBufferLength = UniqueId->UniqueIdLength + sizeof(USHORT);
609 Stack->Parameters.DeviceIoControl.OutputBufferLength = WorkItem->IrpBufferLength;
610 Stack->Parameters.DeviceIoControl.Type3InputBuffer = 0;
611 Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY;
612 Stack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
613
614 Status = IoSetCompletionRoutineEx(WorkItem->DeviceExtension->DeviceObject,
615 Irp,
617 WorkItem,
618 TRUE, TRUE, TRUE);
619 if (!NT_SUCCESS(Status))
620 {
624 return;
625 }
626
627 /* Call the driver */
631}
#define InterlockedExchange
Definition: armddk.h:54
_In_ PIRP Irp
Definition: csq.h:116
VOID RemoveWorkItem(IN PUNIQUE_ID_WORK_ITEM WorkItem)
Definition: notify.c:457
NTSTATUS NTAPI UniqueIdChangeNotifyCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
Definition: notify.c:545
#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:84
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:136
UCHAR UniqueId[1]
Definition: imports.h:137

Referenced by ReconcileThisDatabaseWithMasterWorker().

◆ MountMgrCancel()

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

Definition at line 1592 of file mountmgr.c.

1594{
1596
1597 RemoveEntryList(&(Irp->Tail.Overlay.ListEntry));
1598
1599 IoReleaseCancelSpinLock(Irp->CancelIrql);
1600
1601 Irp->IoStatus.Information = 0;
1602 Irp->IoStatus.Status = STATUS_CANCELLED;
1604}
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#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}
BOOL NTAPI QueryDeviceInformation(_In_ PWCHAR DriveRoot, _Out_ PVOID DeviceInformation, _In_ ULONG BufferSize)
Retrieves disk device information.
Definition: query.c:79
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:169
NTSTATUS GlobalCreateSymbolicLink(IN PUNICODE_STRING DosName, IN PUNICODE_STRING DeviceName)
Definition: symlink.c:120
NTSTATUS GlobalDeleteSymbolicLink(IN PUNICODE_STRING DosName)
Definition: symlink.c:145
VOID MountMgrNotifyNameChange(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING DeviceName, IN BOOLEAN ValidateVolume)
Definition: notify.c:328
VOID PostOnlineNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName)
Definition: notify.c:122
VOID MountMgrNotify(IN PDEVICE_EXTENSION DeviceExtension)
Definition: notify.c:288
BOOLEAN HasDriveLetter(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:167
#define MOUNTMGR_IS_VOLUME_NAME(s)
Definition: mountmgr.h:81
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 626 of file mountmgr.c.

627{
628 FreePool(DeviceInformation->SymbolicName.Buffer);
629 FreePool(DeviceInformation);
630}

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

◆ MountMgrMountedDeviceArrival()

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

Definition at line 855 of file mountmgr.c.

858{
860 GUID StableGuid;
861 HANDLE LinkHandle;
862 ULONG SymLinkCount, i;
863 PLIST_ENTRY NextEntry;
864 PUNICODE_STRING SymLinks;
865 NTSTATUS Status, IntStatus;
867 PSYMLINK_INFORMATION SymlinkInformation;
868 PMOUNTDEV_UNIQUE_ID UniqueId, NewUniqueId;
869 PSAVED_LINK_INFORMATION SavedLinkInformation;
870 PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
871 WCHAR CSymLinkBuffer[RTL_NUMBER_OF(Cunc)], LinkTargetBuffer[MAX_PATH];
872 UNICODE_STRING TargetDeviceName, SuggestedLinkName, DeviceName, VolumeName, DriveLetter, LinkTarget, CSymLink;
873 BOOLEAN HasGuid, HasGptDriveLetter, IsFT, UseOnlyIfThereAreNoOtherLinks;
874 BOOLEAN IsDrvLetter, IsOff, IsVolumeName, SetOnline;
875
876 /* New device = new structure to represent it */
877 DeviceInformation = AllocatePool(sizeof(DEVICE_INFORMATION));
878 if (!DeviceInformation)
879 {
881 }
882
883 /* Initialise device structure */
884 RtlZeroMemory(DeviceInformation, sizeof(DEVICE_INFORMATION));
885 InitializeListHead(&(DeviceInformation->SymbolicLinksListHead));
886 InitializeListHead(&(DeviceInformation->ReplicatedUniqueIdsListHead));
887 InitializeListHead(&(DeviceInformation->AssociatedDevicesHead));
888 DeviceInformation->SymbolicName.Length = SymbolicName->Length;
889 DeviceInformation->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(UNICODE_NULL);
890 DeviceInformation->SymbolicName.Buffer = AllocatePool(DeviceInformation->SymbolicName.MaximumLength);
891 if (!DeviceInformation->SymbolicName.Buffer)
892 {
893 FreePool(DeviceInformation);
895 }
896
897 /* Copy symbolic name */
899 DeviceInformation->SymbolicName.Buffer[DeviceInformation->SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
900 DeviceInformation->ManuallyRegistered = ManuallyRegistered;
901 DeviceInformation->DeviceExtension = DeviceExtension;
902
903 /* Query as much data as possible about device */
905 &TargetDeviceName,
906 &UniqueId,
907 &(DeviceInformation->Removable),
908 &HasGptDriveLetter,
909 &HasGuid,
910 &StableGuid,
911 &IsFT);
912 if (!NT_SUCCESS(Status))
913 {
914 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
915
916 for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
917 NextEntry != &(DeviceExtension->OfflineDeviceListHead);
918 NextEntry = NextEntry->Flink)
919 {
920 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
921
922 if (RtlEqualUnicodeString(&(DeviceInformation->SymbolicName), &(CurrentDevice->SymbolicName), TRUE))
923 {
924 break;
925 }
926 }
927
928 if (NextEntry != &(DeviceExtension->OfflineDeviceListHead))
929 {
930 MountMgrFreeDeadDeviceInfo(DeviceInformation);
931 }
932 else
933 {
934 InsertTailList(&(DeviceExtension->OfflineDeviceListHead), &(DeviceInformation->DeviceListEntry));
935 }
936
937 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
938
939 return Status;
940 }
941
942 /* Save gathered data */
943 DeviceInformation->UniqueId = UniqueId;
944 DeviceInformation->DeviceName = TargetDeviceName;
945 DeviceInformation->KeepLinks = FALSE;
946
947 /* If we found system partition, mark it */
948 if (DeviceExtension->DriveLetterData && UniqueId->UniqueIdLength == DeviceExtension->DriveLetterData->UniqueIdLength)
949 {
950 if (RtlCompareMemory(UniqueId->UniqueId, DeviceExtension->DriveLetterData->UniqueId, UniqueId->UniqueIdLength)
951 == UniqueId->UniqueIdLength)
952 {
953 IoSetSystemPartition(&TargetDeviceName);
954 }
955 }
956
957 /* Check suggested link name */
958 Status = QuerySuggestedLinkName(&(DeviceInformation->SymbolicName),
959 &SuggestedLinkName,
960 &UseOnlyIfThereAreNoOtherLinks);
961 if (!NT_SUCCESS(Status))
962 {
963 SuggestedLinkName.Buffer = NULL;
964 }
965
966 /* If it's OK, set it and save its letter (if any) */
967 if (SuggestedLinkName.Buffer && IsDriveLetter(&SuggestedLinkName))
968 {
969 DeviceInformation->SuggestedDriveLetter = (UCHAR)SuggestedLinkName.Buffer[LETTER_POSITION];
970 }
971
972 /* Acquire driver exclusively */
973 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
974
975 /* Check if we already have device in to prevent double registration */
976 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
977 NextEntry != &(DeviceExtension->DeviceListHead);
978 NextEntry = NextEntry->Flink)
979 {
980 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
981
982 if (RtlEqualUnicodeString(&(CurrentDevice->DeviceName), &TargetDeviceName, TRUE))
983 {
984 break;
985 }
986 }
987
988 /* If we found it, clear ours, and return success, all correct */
989 if (NextEntry != &(DeviceExtension->DeviceListHead))
990 {
991 if (SuggestedLinkName.Buffer)
992 {
993 FreePool(SuggestedLinkName.Buffer);
994 }
995
996 FreePool(UniqueId);
997 FreePool(TargetDeviceName.Buffer);
998 FreePool(DeviceInformation->DeviceName.Buffer);
999 FreePool(DeviceInformation);
1000
1001 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1002
1003 return STATUS_SUCCESS;
1004 }
1005
1006 /* Check if there are symlinks associated with our device in registry */
1007 Status = QuerySymbolicLinkNamesFromStorage(DeviceExtension,
1008 DeviceInformation,
1009 (SuggestedLinkName.Buffer) ? &SuggestedLinkName : NULL,
1010 UseOnlyIfThereAreNoOtherLinks,
1011 &SymLinks,
1012 &SymLinkCount,
1013 HasGuid,
1014 &StableGuid);
1015
1016 /* If our device is a CD-ROM */
1017 if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
1018 {
1019 LinkTarget.Length = 0;
1020 LinkTarget.MaximumLength = sizeof(LinkTargetBuffer);
1021 LinkTarget.Buffer = LinkTargetBuffer;
1022
1023 RtlCopyMemory(CSymLinkBuffer, Cunc, sizeof(Cunc));
1024 RtlInitUnicodeString(&CSymLink, CSymLinkBuffer);
1025
1026 /* Start checking all letters that could have been associated */
1027 for (Letter = L'D'; Letter <= L'Z'; Letter++)
1028 {
1030
1032 &CSymLink,
1034 NULL,
1035 NULL);
1036
1037 /* Try to open the associated symlink */
1039 if (!NT_SUCCESS(Status))
1040 {
1041 continue;
1042 }
1043
1044 /* And query its target */
1045 Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL);
1046 ZwClose(LinkHandle);
1047
1048 if (!NT_SUCCESS(Status))
1049 {
1050 continue;
1051 }
1052
1053 IntStatus = STATUS_UNSUCCESSFUL;
1054 if (!RtlEqualUnicodeString(&LinkTarget, &DeviceInformation->DeviceName, FALSE))
1055 {
1056 continue;
1057 }
1058
1059 /* This link is matching our device, whereas it's not supposed to have any
1060 * symlink associated.
1061 * Delete it
1062 */
1063 if (!SymLinkCount)
1064 {
1065 IoDeleteSymbolicLink(&CSymLink);
1066 continue;
1067 }
1068
1069 /* Now, for all the symlinks, check for ours */
1070 for (i = 0; i < SymLinkCount; i++)
1071 {
1072 if (IsDriveLetter(&(SymLinks[i])))
1073 {
1074 /* If it exists, that's correct */
1075 if (SymLinks[i].Buffer[LETTER_POSITION] == Letter)
1076 {
1077 IntStatus = STATUS_SUCCESS;
1078 }
1079 }
1080 }
1081
1082 /* Useless link, delete it */
1083 if (IntStatus == STATUS_UNSUCCESSFUL)
1084 {
1085 IoDeleteSymbolicLink(&CSymLink);
1086 }
1087 }
1088 }
1089
1090 /* Suggested name is no longer required */
1091 if (SuggestedLinkName.Buffer)
1092 {
1093 FreePool(SuggestedLinkName.Buffer);
1094 }
1095
1096 /* If if failed, ensure we don't take symlinks into account */
1097 if (!NT_SUCCESS(Status))
1098 {
1099 SymLinks = NULL;
1100 SymLinkCount = 0;
1101 }
1102
1103 /* Now we queried them, remove the symlinks */
1104 SavedLinkInformation = RemoveSavedLinks(DeviceExtension, UniqueId);
1105
1106 IsDrvLetter = FALSE;
1107 IsOff = FALSE;
1108 IsVolumeName = FALSE;
1109 /* For all the symlinks */
1110 for (i = 0; i < SymLinkCount; i++)
1111 {
1112 /* Check if our device is a volume */
1113 if (MOUNTMGR_IS_VOLUME_NAME(&(SymLinks[i])))
1114 {
1115 IsVolumeName = TRUE;
1116 }
1117 /* If it has a drive letter */
1118 else if (IsDriveLetter(&(SymLinks[i])))
1119 {
1120 if (IsDrvLetter)
1121 {
1122 DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1123 continue;
1124 }
1125 else
1126 {
1127 IsDrvLetter = TRUE;
1128 }
1129 }
1130
1131 /* And recreate the symlink to our device */
1132 Status = GlobalCreateSymbolicLink(&(SymLinks[i]), &TargetDeviceName);
1133 if (!NT_SUCCESS(Status))
1134 {
1135 BOOLEAN LinkError = TRUE;
1136
1137 if ((SavedLinkInformation && !RedirectSavedLink(SavedLinkInformation, &(SymLinks[i]), &TargetDeviceName)) ||
1138 !SavedLinkInformation)
1139 {
1141 if (NT_SUCCESS(Status))
1142 {
1143 LinkError = RtlEqualUnicodeString(&TargetDeviceName, &DeviceName, TRUE);
1144 FreePool(DeviceName.Buffer);
1145 }
1146
1147 if (!LinkError)
1148 {
1149 if (IsDriveLetter(&(SymLinks[i])))
1150 {
1151 IsDrvLetter = FALSE;
1152 DeleteFromLocalDatabase(&(SymLinks[i]), UniqueId);
1153 }
1154
1155 FreePool(SymLinks[i].Buffer);
1156 continue;
1157 }
1158 }
1159 }
1160
1161 /* Check if was offline */
1162 if (IsOffline(&(SymLinks[i])))
1163 {
1164 IsOff = TRUE;
1165 }
1166
1167 /* Finally, associate this symlink with the device */
1168 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1169 if (!SymlinkInformation)
1170 {
1171 GlobalDeleteSymbolicLink(&(SymLinks[i]));
1172 FreePool(SymLinks[i].Buffer);
1173 continue;
1174 }
1175
1176 SymlinkInformation->Name = SymLinks[i];
1177 SymlinkInformation->Online = TRUE;
1178
1179 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1180 &(SymlinkInformation->SymbolicLinksListEntry));
1181 }
1182
1183 /* Now, for all the recreated symlinks, notify their recreation */
1184 for (NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1185 NextEntry != &(DeviceInformation->SymbolicLinksListHead);
1186 NextEntry = NextEntry->Flink)
1187 {
1188 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1189
1190 SendLinkCreated(&(SymlinkInformation->Name));
1191 }
1192
1193 /* If we had saved links, it's time to free them */
1194 if (SavedLinkInformation)
1195 {
1196 MountMgrFreeSavedLink(SavedLinkInformation);
1197 }
1198
1199 /* If our device doesn't have a volume name */
1200 if (!IsVolumeName)
1201 {
1202 /* It's time to create one */
1204 if (NT_SUCCESS(Status))
1205 {
1206 /* Write it to global database */
1210 REG_BINARY,
1211 UniqueId->UniqueId,
1212 UniqueId->UniqueIdLength);
1213
1214 /* And create the symlink */
1215 GlobalCreateSymbolicLink(&VolumeName, &TargetDeviceName);
1216
1217 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1218 if (!SymlinkInformation)
1219 {
1221 }
1222 /* Finally, associate it with the device and notify creation */
1223 else
1224 {
1225 SymlinkInformation->Name = VolumeName;
1226 SymlinkInformation->Online = TRUE;
1227 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1228 &(SymlinkInformation->SymbolicLinksListEntry));
1229
1231 }
1232 }
1233 }
1234
1235 /* If we found a drive letter, then, ignore the suggested one */
1236 if (IsDrvLetter)
1237 {
1238 DeviceInformation->SuggestedDriveLetter = 0;
1239 }
1240 /* Else, it's time to set up one */
1241 else if ((!DeviceExtension->NoAutoMount || DeviceInformation->Removable) &&
1242 DeviceExtension->AutomaticDriveLetter &&
1243 (HasGptDriveLetter || DeviceInformation->SuggestedDriveLetter) &&
1244 !HasNoDriveLetterEntry(UniqueId))
1245 {
1246 /* Create a new drive letter */
1247 Status = CreateNewDriveLetterName(&DriveLetter, &TargetDeviceName,
1248 DeviceInformation->SuggestedDriveLetter,
1249 NULL);
1250 if (!NT_SUCCESS(Status))
1251 {
1252 CreateNoDriveLetterEntry(UniqueId);
1253 }
1254 else
1255 {
1256 /* Save it to global database */
1259 DriveLetter.Buffer,
1260 REG_BINARY,
1261 UniqueId->UniqueId,
1262 UniqueId->UniqueIdLength);
1263
1264 /* Associate it with the device and notify creation */
1265 SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
1266 if (!SymlinkInformation)
1267 {
1268 FreePool(DriveLetter.Buffer);
1269 }
1270 else
1271 {
1272 SymlinkInformation->Name = DriveLetter;
1273 SymlinkInformation->Online = TRUE;
1274 InsertTailList(&(DeviceInformation->SymbolicLinksListHead),
1275 &(SymlinkInformation->SymbolicLinksListEntry));
1276
1277 SendLinkCreated(&DriveLetter);
1278 }
1279 }
1280 }
1281
1282 /* If that's a PnP device, register for notifications */
1283 if (!ManuallyRegistered)
1284 {
1285 RegisterForTargetDeviceNotification(DeviceExtension, DeviceInformation);
1286 }
1287
1288 /* Finally, insert the device into our devices list */
1289 InsertTailList(&(DeviceExtension->DeviceListHead), &(DeviceInformation->DeviceListEntry));
1290
1291 /* Copy device unique ID */
1292 NewUniqueId = AllocatePool(UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1293 if (NewUniqueId)
1294 {
1295 NewUniqueId->UniqueIdLength = UniqueId->UniqueIdLength;
1296 RtlCopyMemory(NewUniqueId->UniqueId, UniqueId->UniqueId, UniqueId->UniqueIdLength);
1297 }
1298
1299 /* Skip online notifications if the device is offline or a FT volume */
1300 if (IsOff || IsFT)
1301 DeviceInformation->SkipNotifications = TRUE;
1302
1303 /* If automount is enabled or the device was already mounted, send now
1304 * the online notification if needed; otherwise, defer its posting */
1305 if (!DeviceExtension->NoAutoMount || IsDrvLetter)
1306 SetOnline = !DeviceInformation->SkipNotifications;
1307 else
1308 SetOnline = FALSE;
1309
1310 /* Finally, release the exclusive lock */
1311 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1312
1313 /* Set the device online now if necessary */
1314 if (SetOnline)
1316
1317 /* If we had symlinks (from storage), free them */
1318 if (SymLinks)
1319 {
1320 FreePool(SymLinks);
1321 }
1322
1323 /* Notify about unique id change */
1324 if (NewUniqueId)
1325 {
1326 IssueUniqueIdChangeNotify(DeviceExtension, SymbolicName, NewUniqueId);
1327 FreePool(NewUniqueId);
1328 }
1329
1330 /* If this drive was set to have a drive letter automatically
1331 * Now it's back, local databases sync will be required
1332 */
1333 if (DeviceExtension->AutomaticDriveLetter)
1334 {
1335 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1336
1337 ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
1338
1339 NextEntry = DeviceExtension->DeviceListHead.Flink;
1340 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1341 while (CurrentDevice != DeviceInformation)
1342 {
1343 if (!CurrentDevice->NoDatabase)
1344 {
1345 ReconcileThisDatabaseWithMaster(DeviceExtension, CurrentDevice);
1346 }
1347
1348 NextEntry = NextEntry->Flink;
1349 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1350 }
1351
1352 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1353 }
1354
1355 return STATUS_SUCCESS;
1356}
#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:451
VOID SendOnlineNotification(IN PUNICODE_STRING SymbolicName)
Definition: notify.c:38
NTSTATUS CreateNewVolumeName(OUT PUNICODE_STRING VolumeName, IN PGUID VolumeGuid OPTIONAL)
Definition: symlink.c:399
UNICODE_STRING DeviceCdRom
Definition: symlink.c:44
VOID RegisterForTargetDeviceNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: notify.c:250
#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:637
NTSTATUS QuerySuggestedLinkName(IN PUNICODE_STRING SymbolicName, OUT PUNICODE_STRING SuggestedLinkName, OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks)
Definition: symlink.c:621
PSAVED_LINK_INFORMATION RemoveSavedLinks(IN PDEVICE_EXTENSION DeviceExtension, IN PMOUNTDEV_UNIQUE_ID UniqueId)
Definition: symlink.c:577
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:717
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
BOOLEAN IsOffline(PUNICODE_STRING SymbolicName)
Definition: mountmgr.c:130
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:192
VOID MountMgrFreeDeadDeviceInfo(IN PDEVICE_INFORMATION DeviceInformation)
Definition: mountmgr.c:626
VOID MountMgrFreeSavedLink(IN PSAVED_LINK_INFORMATION SavedLinkInformation)
Definition: mountmgr.c:691
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 1362 of file mountmgr.c.

1364{
1365 PLIST_ENTRY NextEntry, DeviceEntry;
1366 PUNIQUE_ID_REPLICATE UniqueIdReplicate;
1367 PSYMLINK_INFORMATION SymlinkInformation;
1369 PSAVED_LINK_INFORMATION SavedLinkInformation = NULL;
1370 PDEVICE_INFORMATION DeviceInformation, CurrentDevice;
1371
1372 /* Acquire device exclusively */
1373 KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
1374
1375 /* Look for the leaving device */
1376 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1377 NextEntry != &(DeviceExtension->DeviceListHead);
1378 NextEntry = NextEntry->Flink)
1379 {
1380 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1381
1382 if (!RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE))
1383 {
1384 break;
1385 }
1386 }
1387
1388 /* If we found it */
1389 if (NextEntry != &(DeviceExtension->DeviceListHead))
1390 {
1391 /* If it's asked to keep links, then, prepare to save them */
1392 if (DeviceInformation->KeepLinks)
1393 {
1394 SavedLinkInformation = AllocatePool(sizeof(SAVED_LINK_INFORMATION));
1395 if (!SavedLinkInformation)
1396 {
1397 DeviceInformation->KeepLinks = FALSE;
1398 }
1399 }
1400
1401 /* If it's possible (and asked), start to save them */
1402 if (DeviceInformation->KeepLinks)
1403 {
1404 InsertTailList(&(DeviceExtension->SavedLinksListHead), &(SavedLinkInformation->SavedLinksListEntry));
1405 InitializeListHead(&(SavedLinkInformation->SymbolicLinksListHead));
1406 SavedLinkInformation->UniqueId = DeviceInformation->UniqueId;
1407 }
1408
1409 /* For all the symlinks */
1410 while (!IsListEmpty(&(DeviceInformation->SymbolicLinksListHead)))
1411 {
1412 NextEntry = RemoveHeadList(&(DeviceInformation->SymbolicLinksListHead));
1413 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1414
1415 /* If we have to, save the link */
1416 if (DeviceInformation->KeepLinks)
1417 {
1418 InsertTailList(&(SavedLinkInformation->SymbolicLinksListHead), &(SymlinkInformation->SymbolicLinksListEntry));
1419 }
1420 /* Otherwise, just release it */
1421 else
1422 {
1423 GlobalDeleteSymbolicLink(&(SymlinkInformation->Name));
1424 FreePool(SymlinkInformation->Name.Buffer);
1425 FreePool(SymlinkInformation);
1426 }
1427 }
1428
1429 /* Free all the replicated unique IDs */
1430 while (!IsListEmpty(&(DeviceInformation->ReplicatedUniqueIdsListHead)))
1431 {
1432 NextEntry = RemoveHeadList(&(DeviceInformation->ReplicatedUniqueIdsListHead));
1433 UniqueIdReplicate = CONTAINING_RECORD(NextEntry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
1434
1435
1436 FreePool(UniqueIdReplicate->UniqueId);
1437 FreePool(UniqueIdReplicate);
1438 }
1439
1440 while (!IsListEmpty(&(DeviceInformation->AssociatedDevicesHead)))
1441 {
1442 NextEntry = RemoveHeadList(&(DeviceInformation->AssociatedDevicesHead));
1443 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1444
1445 DeviceInformation->NoDatabase = TRUE;
1446 FreePool(AssociatedDevice->String.Buffer);
1448 }
1449
1450 /* Remove device from the device list */
1451 RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1452
1453 /* If there are still devices, check if some were associated with ours */
1454 if (!IsListEmpty(&(DeviceInformation->DeviceListEntry)))
1455 {
1456 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
1457 NextEntry != &(DeviceExtension->DeviceListHead);
1458 NextEntry = NextEntry->Flink)
1459 {
1460 CurrentDevice = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1461
1462 /* And then, remove them */
1463 DeviceEntry = CurrentDevice->AssociatedDevicesHead.Flink;
1464 while (DeviceEntry != &(CurrentDevice->AssociatedDevicesHead))
1465 {
1466 AssociatedDevice = CONTAINING_RECORD(NextEntry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1467 DeviceEntry = DeviceEntry->Flink;
1468
1469 if (AssociatedDevice->DeviceInformation != DeviceInformation)
1470 {
1471 continue;
1472 }
1473
1474 RemoveEntryList(&(AssociatedDevice->AssociatedDevicesEntry));
1475 FreePool(AssociatedDevice->String.Buffer);
1477 }
1478 }
1479 }
1480
1481 /* Finally, clean up device name, symbolic name */
1482 FreePool(DeviceInformation->SymbolicName.Buffer);
1483 if (!DeviceInformation->KeepLinks)
1484 {
1485 FreePool(DeviceInformation->UniqueId);
1486 }
1487 FreePool(DeviceInformation->DeviceName.Buffer);
1488
1489 /* Unregister notifications */
1490 if (DeviceInformation->TargetDeviceNotificationEntry)
1491 {
1493 }
1494
1495 /* And leave */
1496 FreePool(DeviceInformation);
1497 }
1498 else
1499 {
1500 /* We didn't find device, perhaps because it was offline */
1501 for (NextEntry = DeviceExtension->OfflineDeviceListHead.Flink;
1502 NextEntry != &(DeviceExtension->OfflineDeviceListHead);
1503 NextEntry = NextEntry->Flink)
1504 {
1505 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
1506
1507 /* It was, remove it */
1508 if (RtlCompareUnicodeString(&(DeviceInformation->SymbolicName), DeviceName, TRUE) == 0)
1509 {
1510 RemoveEntryList(&(DeviceInformation->DeviceListEntry));
1511 MountMgrFreeDeadDeviceInfo(DeviceInformation);
1512 break;
1513 }
1514 }
1515 }
1516
1517 /* Release driver */
1518 KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
1519}
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(_In_ PVOID NotificationEntry)
Definition: pnpnotify.c:480
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 288 of file notify.c.

289{
290 PIRP Irp;
292 LIST_ENTRY CopyList;
293 PLIST_ENTRY NextEntry;
294
295 /* Increase the epic number */
296 DeviceExtension->EpicNumber++;
297
298 InitializeListHead(&CopyList);
299
300 /* Copy all the pending IRPs for notification */
302 while (!IsListEmpty(&(DeviceExtension->IrpListHead)))
303 {
304 NextEntry = RemoveHeadList(&(DeviceExtension->IrpListHead));
305 Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
307 InsertTailList(&CopyList, &(Irp->Tail.Overlay.ListEntry));
308 }
310
311 /* Then, notify them one by one */
312 while (!IsListEmpty(&CopyList))
313 {
314 NextEntry = RemoveHeadList(&CopyList);
315 Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
316
317 *((PULONG)Irp->AssociatedIrp.SystemBuffer) = DeviceExtension->EpicNumber;
318 Irp->IoStatus.Information = sizeof(DeviceExtension->EpicNumber);
319
321 }
322}
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 328 of file notify.c.

331{
332 PIRP Irp;
335 PLIST_ENTRY NextEntry;
340 PDEVICE_RELATIONS DeviceRelations;
341 PDEVICE_INFORMATION DeviceInformation;
342 TARGET_DEVICE_CUSTOM_NOTIFICATION DeviceNotification;
343
344 /* If we have to validate volume */
345 if (ValidateVolume)
346 {
347 /* Then, ensure we can find the device */
348 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
349 NextEntry != &DeviceExtension->DeviceListHead;
350 NextEntry = NextEntry->Flink)
351 {
352 DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
353 if (RtlCompareUnicodeString(DeviceName, &(DeviceInformation->DeviceName), TRUE) == 0)
354 {
355 break;
356 }
357 }
358
359 /* No need to notify for a PnP device or if we didn't find the device */
360 if (NextEntry == &(DeviceExtension->DeviceListHead) ||
361 !DeviceInformation->ManuallyRegistered)
362 {
363 return;
364 }
365 }
366
367 /* Then, get device object */
370 &FileObject,
371 &DeviceObject);
372 if (!NT_SUCCESS(Status))
373 {
374 return;
375 }
376
378
380
381 /* Set up empty IRP (yes, yes!) */
384 NULL,
385 0,
386 NULL,
387 0,
388 FALSE,
389 &Event,
391 if (!Irp)
392 {
395 return;
396 }
397
399
400 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
401 Irp->IoStatus.Information = 0;
402
403 /* Properly set it, we want to query device relations */
404 Stack->MajorFunction = IRP_MJ_PNP;
405 Stack->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
406 Stack->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
407 Stack->FileObject = FileObject;
408
409 /* And call driver */
411 if (Status == STATUS_PENDING)
412 {
415 }
416
419
420 if (!NT_SUCCESS(Status))
421 {
422 return;
423 }
424
425 /* Validate device return */
427 if (DeviceRelations->Count < 1)
428 {
429 ExFreePool(DeviceRelations);
430 return;
431 }
432
433 DeviceObject = DeviceRelations->Objects[0];
434 ExFreePool(DeviceRelations);
435
436 /* Set up real notification */
437 DeviceNotification.Version = 1;
438 DeviceNotification.Size = sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION);
439 DeviceNotification.Event = GUID_IO_VOLUME_NAME_CHANGE;
440 DeviceNotification.FileObject = NULL;
441 DeviceNotification.NameBufferOffset = -1;
442
443 /* And report */
445 &DeviceNotification,
446 NULL, NULL);
447
449
450 return;
451}
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#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
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 849 of file symlink.c.

851{
853 HANDLE LinkHandle;
855
856 /* Open the symbolic link */
860 NULL,
861 NULL);
862
863 Status = ZwOpenSymbolicLinkObject(&LinkHandle,
866 if (!NT_SUCCESS(Status))
867 {
868 return Status;
869 }
870
871 /* Query its target */
872 Status = ZwQuerySymbolicLinkObject(LinkHandle,
874 NULL);
875
876 ZwClose(LinkHandle);
877
878 if (!NT_SUCCESS(Status))
879 {
880 return Status;
881 }
882
883 if (LinkTarget->Length <= sizeof(WCHAR))
884 {
885 return Status;
886 }
887
888 /* If it's not finished by \, just return */
889 if (LinkTarget->Buffer[LinkTarget->Length / sizeof(WCHAR) - 1] != L'\\')
890 {
891 return Status;
892 }
893
894 /* Otherwise, ensure to drop the tailing \ */
895 LinkTarget->Length -= sizeof(WCHAR);
897
898 return Status;
899}
#define GENERIC_READ
Definition: compat.h:135

Referenced by MountMgrVolumeMountPointCreated(), and MountMgrVolumeMountPointDeleted().

◆ 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 122 of file notify.c.

124{
127
128 /* Allocate a notification work item */
130 if (!WorkItem)
131 {
132 return;
133 }
134
136 WorkItem->DeviceExtension = DeviceExtension;
137 WorkItem->SymbolicName.Length = SymbolicName->Length;
138 WorkItem->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(WCHAR);
139 WorkItem->SymbolicName.Buffer = AllocatePool(WorkItem->SymbolicName.MaximumLength);
140 if (!WorkItem->SymbolicName.Buffer)
141 {
143 return;
144 }
145
147 WorkItem->SymbolicName.Buffer[SymbolicName->Length / sizeof(WCHAR)] = UNICODE_NULL;
148
149 KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
150 DeviceExtension->OnlineNotificationCount++;
151
152 /* If no worker are active */
153 if (DeviceExtension->OnlineNotificationWorkerActive == 0)
154 {
155 /* Queue that one for execution */
156 DeviceExtension->OnlineNotificationWorkerActive = 1;
158 }
159 else
160 {
161 /* Otherwise, just put it in the queue list */
162 InsertTailList(&(DeviceExtension->OnlineNotificationListHead), &(WorkItem->WorkItem.List));
163 }
164
165 KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
166
167 return;
168}
VOID NTAPI SendOnlineNotificationWorker(IN PVOID Parameter)
Definition: notify.c:73
#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_opt_ PUNICODE_STRING  DeviceName,
_Out_opt_ PMOUNTDEV_UNIQUE_ID UniqueId,
_Out_opt_ PBOOLEAN  Removable,
_Out_opt_ PBOOLEAN  GptDriveLetter,
_Out_opt_ PBOOLEAN  HasGuid,
_Inout_opt_ LPGUID  StableGuid,
_Out_opt_ PBOOLEAN  IsFT 
)

Definition at line 274 of file mountmgr.c.

283{
285 USHORT Size;
286 BOOLEAN IsRemovable;
292 STORAGE_DEVICE_NUMBER StorageDeviceNumber;
294
295 /* Get device associated with the symbolic name */
298 &FileObject,
299 &DeviceObject);
300 if (!NT_SUCCESS(Status))
301 {
302 return Status;
303 }
304
305 /* The associate FO can't have a file name */
306 if (FileObject->FileName.Length)
307 {
310 }
311
312 /* Check if it's removable & return to the user (if asked to) */
313 IsRemovable = (FileObject->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA);
314 if (Removable)
315 {
316 *Removable = IsRemovable;
317 }
318
319 /* Get the attached device */
321
322 /* If we've been asked for a GPT drive letter */
323 if (GptDriveLetter)
324 {
325 /* Consider it has one */
326 *GptDriveLetter = TRUE;
327
328 if (!IsRemovable)
329 {
330 /* Query the GPT attributes */
331 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_VOLUME_GET_GPT_ATTRIBUTES,
333 NULL,
334 0,
335 &GptAttributes,
336 sizeof(GptAttributes),
337 NULL);
338 /* Failure isn't major */
339 if (!NT_SUCCESS(Status))
340 {
342 }
343 /* Check if it has a drive letter */
344 else if (GptAttributes.GptAttributes & GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER)
345 {
346 *GptDriveLetter = FALSE;
347 }
348 }
349 }
350
351 /* If caller wants to know if this is a FT volume */
352 if (IsFT)
353 {
354 /* Suppose it's not */
355 *IsFT = FALSE;
356
357 /* FT volume can't be removable */
358 if (!IsRemovable)
359 {
360 /* Query partition information */
361 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX,
363 NULL,
364 0,
366 sizeof(PartitionInfo),
367 NULL);
368 /* Failure isn't major */
369 if (!NT_SUCCESS(Status))
370 {
372 }
373 /* Check if this is a FT volume */
374 else if ((PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR) &&
375 IsFTPartition(PartitionInfo.Mbr.PartitionType))
376 {
377 *IsFT = TRUE;
378 }
379
380 /* It looks like a FT volume. Verify it is really one by checking
381 * that it does NOT lie on a specific storage device (i.e. it is
382 * not a basic volume). */
383 if (*IsFT)
384 {
385 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER,
387 NULL,
388 0,
389 &StorageDeviceNumber,
390 sizeof(StorageDeviceNumber),
391 NULL);
392 if (!NT_SUCCESS(Status))
394 else
395 *IsFT = FALSE; // Succeeded, so this cannot be a FT volume.
396 }
397 }
398 }
399
400 /* If caller needs device name */
401 if (DeviceName)
402 {
403 /* Allocate a buffer just to request length */
405 if (!Name)
406 {
410 }
411
412 /* Query device name */
413 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
415 NULL,
416 0,
417 Name,
418 sizeof(MOUNTDEV_NAME),
419 FileObject);
420 /* Retry with appropriate length */
422 {
423 Size = Name->NameLength + sizeof(MOUNTDEV_NAME);
424
425 FreePool(Name);
426
427 /* Allocate proper size */
429 if (!Name)
430 {
434 }
435
436 /* And query name (for real that time) */
437 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
439 NULL,
440 0,
441 Name,
442 Size,
443 FileObject);
444 }
445
446 if (NT_SUCCESS(Status))
447 {
448 /* Copy back found name to the caller */
449 DeviceName->Length = Name->NameLength;
450 DeviceName->MaximumLength = Name->NameLength + sizeof(WCHAR);
451 DeviceName->Buffer = AllocatePool(DeviceName->MaximumLength);
452 if (!DeviceName->Buffer)
453 {
455 }
456 else
457 {
458 RtlCopyMemory(DeviceName->Buffer, Name->Name, Name->NameLength);
459 DeviceName->Buffer[Name->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
460 }
461 }
462
463 FreePool(Name);
464 }
465
466 if (!NT_SUCCESS(Status))
467 {
470 return Status;
471 }
472
473 /* If caller wants device unique ID */
474 if (UniqueId)
475 {
476 /* Prepare buffer to probe length */
478 if (!Id)
479 {
483 }
484
485 /* Query unique ID length */
486 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
488 NULL,
489 0,
490 Id,
491 sizeof(MOUNTDEV_UNIQUE_ID),
492 FileObject);
493 /* Retry with appropriate length */
495 {
496 Size = Id->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID);
497
498 FreePool(Id);
499
500 /* Allocate the correct buffer */
502 if (!Id)
503 {
507 }
508
509 /* Query unique ID */
510 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID,
512 NULL,
513 0,
514 Id,
515 Size,
516 FileObject);
517 }
518
519 /* Hands back unique ID */
520 if (NT_SUCCESS(Status))
521 {
522 *UniqueId = Id;
523 }
524 else
525 {
526 /* In case of failure, also free the rest */
527 FreePool(Id);
528 if (DeviceName->Length)
529 FreePool(DeviceName->Buffer);
530
533 return Status;
534 }
535 }
536
537 /* If user wants to know about GUID */
538 if (HasGuid)
539 {
540 /* Query device stable GUID */
541 NTSTATUS IntStatus;
542 IntStatus = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_STABLE_GUID,
544 NULL,
545 0,
546 StableGuid,
547 sizeof(GUID),
548 FileObject);
549 *HasGuid = NT_SUCCESS(IntStatus);
550 }
551
554 return Status;
555}
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:91
#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID
Definition: imports.h:255
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:78
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define IsFTPartition(PartitionType)
Definition: ntdddisk.h:315
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_VOLUME_GET_GPT_ATTRIBUTES
Definition: ntddvol.h:133
@ 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(), and MountMgrMountedDeviceArrival().

◆ 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}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
struct _MOUNTMGR_MOUNT_POINTS * PMOUNTMGR_MOUNT_POINTS
struct _MOUNTMGR_MOUNT_POINTS MOUNTMGR_MOUNT_POINTS
MOUNTMGR_MOUNT_POINT MountPoints[1]
Definition: imports.h:175
USHORT DeviceNameLength
Definition: imports.h:169
USHORT SymbolicLinkNameLength
Definition: imports.h:165
ULONG SymbolicLinkNameOffset
Definition: imports.h:164
uint16_t * PWSTR
Definition: typedefs.h:56

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 621 of file symlink.c.

624{
626 USHORT NameLength;
629 PMOUNTDEV_SUGGESTED_LINK_NAME IoCtlSuggested;
630
631 /* First, get device */
634 &FileObject,
635 &DeviceObject);
636 if (!NT_SUCCESS(Status))
637 {
638 return Status;
639 }
640
641 /* Then, get attached device */
643
644 /* Then, prepare buffer to query suggested name */
645 IoCtlSuggested = AllocatePool(sizeof(MOUNTDEV_SUGGESTED_LINK_NAME));
646 if (!IoCtlSuggested)
647 {
649 goto Dereference;
650 }
651
652 /* Prepare request */
653 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME,
655 NULL,
656 0,
657 IoCtlSuggested,
659 FileObject);
660 /* Retry with appropriate length */
662 {
663 /* Reallocate big enough buffer */
664 NameLength = IoCtlSuggested->NameLength + sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
665 FreePool(IoCtlSuggested);
666
667 IoCtlSuggested = AllocatePool(NameLength);
668 if (!IoCtlSuggested)
669 {
671 goto Dereference;
672 }
673
674 /* And re-ask */
675 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME,
677 NULL,
678 0,
679 IoCtlSuggested,
680 NameLength,
681 FileObject);
682 }
683 if (!NT_SUCCESS(Status))
684 goto Release;
685
686 /* Now we have suggested name, copy it */
687 SuggestedLinkName->Length = IoCtlSuggested->NameLength;
688 SuggestedLinkName->MaximumLength = IoCtlSuggested->NameLength + sizeof(UNICODE_NULL);
689 SuggestedLinkName->Buffer = AllocatePool(IoCtlSuggested->NameLength + sizeof(UNICODE_NULL));
690 if (!SuggestedLinkName->Buffer)
691 {
693 }
694 else
695 {
696 RtlCopyMemory(SuggestedLinkName->Buffer, IoCtlSuggested->Name, IoCtlSuggested->NameLength);
697 SuggestedLinkName->Buffer[SuggestedLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL;
698 }
699
700 /* Also return its priority */
701 *UseOnlyIfThereAreNoOtherLinks = IoCtlSuggested->UseOnlyIfThereAreNoOtherLinks;
702
703Release:
704 FreePool(IoCtlSuggested);
705
706Dereference:
709
710 return Status;
711}
_In_ BOOLEAN Release
Definition: cdrom.h:920
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:97
struct _MOUNTDEV_SUGGESTED_LINK_NAME MOUNTDEV_SUGGESTED_LINK_NAME

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 451 of file symlink.c.

459{
461 BOOLEAN WriteNew;
463
464 UNREFERENCED_PARAMETER(DeviceExtension);
465
466 /* First of all, count links */
469 QueryTable[0].EntryContext = SymLinkCount;
470 *SymLinkCount = 0;
471
475 DeviceInformation->UniqueId,
476 NULL);
477 if (!NT_SUCCESS(Status))
478 {
479 *SymLinkCount = 0;
480 }
481
482 /* Check if we have to write a new one first */
483 if (SuggestedLinkName && !IsDriveLetter(SuggestedLinkName) &&
484 UseOnlyIfThereAreNoOtherLinks && *SymLinkCount == 0)
485 {
486 WriteNew = TRUE;
487 }
488 else
489 {
490 WriteNew = FALSE;
491 }
492
493 /* If has GUID, it makes one more link */
494 if (HasGuid)
495 {
496 (*SymLinkCount)++;
497 }
498
499 if (WriteNew)
500 {
501 /* Write link */
504 SuggestedLinkName->Buffer,
506 DeviceInformation->UniqueId->UniqueId,
507 DeviceInformation->UniqueId->UniqueIdLength);
508
509 /* And recount all the needed links */
512 QueryTable[0].EntryContext = SymLinkCount;
513 *SymLinkCount = 0;
514
518 DeviceInformation->UniqueId,
519 NULL);
520 if (!NT_SUCCESS(Status))
521 {
522 return STATUS_NOT_FOUND;
523 }
524 }
525
526 /* Not links found? */
527 if (!*SymLinkCount)
528 {
529 return STATUS_NOT_FOUND;
530 }
531
532 /* Allocate a buffer big enough to hold symlinks (table of unicode strings) */
533 *SymLinks = AllocatePool(*SymLinkCount * sizeof(UNICODE_STRING));
534 if (!*SymLinks)
535 {
537 }
538
539 /* Prepare to query links */
540 RtlZeroMemory(*SymLinks, *SymLinkCount * sizeof(UNICODE_STRING));
543
544 /* No GUID? Keep it that way */
545 if (!HasGuid)
546 {
547 QueryTable[0].EntryContext = *SymLinks;
548 }
549 /* Otherwise, first create volume name */
550 else
551 {
552 Status = CreateNewVolumeName(SymLinks[0], Guid);
553 if (!NT_SUCCESS(Status))
554 {
555 FreePool(*SymLinks);
556 return Status;
557 }
558
559 /* Skip first link (ours) */
560 QueryTable[0].EntryContext = *SymLinks + 1;
561 }
562
563 /* Now, query */
567 DeviceInformation->UniqueId,
568 NULL);
569
570 return STATUS_SUCCESS;
571}
#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:746
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
struct _REPARSE_DATA_BUFFER::@312::@315 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 the worker thread isn't started yet, automatic drive letter is
1645 * enabled but automount disabled, manually set mounted volumes online.
1646 * Otherwise, they will be set online during database reconciliation. */
1647 if (DeviceExtension->WorkerThreadStatus == 0 &&
1648 DeviceExtension->AutomaticDriveLetter &&
1649 DeviceExtension->NoAutoMount)
1650 {
1651 OnlineMountedVolumes(DeviceExtension, DeviceInformation);
1652 }
1653}
VOID OnlineMountedVolumes(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation)
Definition: database.c:1460
VOID NTAPI ReconcileThisDatabaseWithMasterWorker(IN PVOID Parameter)
Definition: database.c:560
NTSTATUS QueueWorkItem(IN PDEVICE_EXTENSION DeviceExtension, IN PRECONCILE_WORK_ITEM WorkItem, IN PVOID Context)
Definition: database.c:1261

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

◆ ReconcileThisDatabaseWithMasterWorker()

VOID NTAPI ReconcileThisDatabaseWithMasterWorker ( IN PVOID  Parameter)

Definition at line 560 of file database.c.

561{
566 PMOUNTDEV_UNIQUE_ID UniqueId;
567 PDATABASE_ENTRY DatabaseEntry;
568 HANDLE DatabaseHandle, Handle;
571 PDEVICE_INFORMATION ListDeviceInfo;
572 PLIST_ENTRY Entry, EntryInfo, NextEntry;
574 BOOLEAN HardwareErrors, Restart, FailedFinding;
575 WCHAR FileNameBuffer[0x8], SymbolicNameBuffer[100];
577 FILE_REPARSE_POINT_INFORMATION ReparsePointInformation, SavedReparsePointInformation;
578 PDEVICE_EXTENSION DeviceExtension = ((PRECONCILE_WORK_ITEM_CONTEXT)Parameter)->DeviceExtension;
579 PDEVICE_INFORMATION DeviceInformation = ((PRECONCILE_WORK_ITEM_CONTEXT)Parameter)->DeviceInformation;
580
581 /* We're unloading, do nothing */
582 if (Unloading)
583 {
584 return;
585 }
586
587 /* Lock remote DB */
588 if (!NT_SUCCESS(WaitForRemoteDatabaseSemaphore(DeviceExtension)))
589 {
590 return;
591 }
592
593 /* Recheck for unloading */
594 if (Unloading)
595 {
596 goto ReleaseRDS;
597 }
598
599 /* Find the DB to reconcile */
600 KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
601 for (Entry = DeviceExtension->DeviceListHead.Flink;
602 Entry != &DeviceExtension->DeviceListHead;
603 Entry = Entry->Flink)
604 {
605 ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
606 if (ListDeviceInfo == DeviceInformation)
607 {
608 break;
609 }
610 }
611
612 /* If not found, or if removable, bail out */
613 if (Entry == &DeviceExtension->DeviceListHead || DeviceInformation->Removable)
614 {
615 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
616 goto ReleaseRDS;
617 }
618
619 /* Get our device object */
621 if (!NT_SUCCESS(Status))
622 {
623 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
624 goto ReleaseRDS;
625 }
626
627 /* Mark mounted only if not unloading */
628 if (!(DeviceObject->Flags & DO_UNLOAD_PENDING))
629 {
630 InterlockedExchangeAdd(&ListDeviceInfo->MountState, 1);
631 }
632
634
635 /* Force default: no DB, and need for reconcile */
636 DeviceInformation->NeedsReconcile = TRUE;
637 DeviceInformation->NoDatabase = TRUE;
638 FailedFinding = FALSE;
639
640 /* Remove any associated device that refers to the DB to reconcile */
641 for (Entry = DeviceExtension->DeviceListHead.Flink;
642 Entry != &DeviceExtension->DeviceListHead;
643 Entry = Entry->Flink)
644 {
645 ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
646
647 EntryInfo = ListDeviceInfo->AssociatedDevicesHead.Flink;
648 while (EntryInfo != &ListDeviceInfo->AssociatedDevicesHead)
649 {
650 AssociatedDevice = CONTAINING_RECORD(EntryInfo, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
651 NextEntry = EntryInfo->Flink;
652
653 if (AssociatedDevice->DeviceInformation == DeviceInformation)
654 {
655 RemoveEntryList(&AssociatedDevice->AssociatedDevicesEntry);
656 FreePool(AssociatedDevice->String.Buffer);
658 }
659
660 EntryInfo = NextEntry;
661 }
662 }
663
664 /* Open the remote database */
665 DatabaseHandle = OpenRemoteDatabase(DeviceInformation, FALSE);
666
667 /* Prepare a string with reparse point index */
668 ReparseFile.Length = 0;
669 ReparseFile.MaximumLength = DeviceInformation->DeviceName.Length
671 + sizeof(UNICODE_NULL);
672 ReparseFile.Buffer = AllocatePool(ReparseFile.MaximumLength);
673 if (!ReparseFile.Buffer)
674 {
675 if (DatabaseHandle != 0)
676 {
677 CloseRemoteDatabase(DatabaseHandle);
678 }
679 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
680 goto ReleaseRDS;
681 }
682
683 RtlAppendUnicodeStringToString(&ReparseFile, &DeviceInformation->DeviceName);
685 ReparseFile.Buffer[ReparseFile.Length / sizeof(WCHAR)] = UNICODE_NULL;
686
688 &ReparseFile,
690 NULL,
691 NULL);
692
693 /* Open reparse point directory */
694 HardwareErrors = IoSetThreadHardErrorMode(FALSE);
701 IoSetThreadHardErrorMode(HardwareErrors);
702
703 FreePool(ReparseFile.Buffer);
704
705 if (!NT_SUCCESS(Status))
706 {
707 if (DatabaseHandle != 0)
708 {
709 TruncateRemoteDatabase(DatabaseHandle, 0);
710 CloseRemoteDatabase(DatabaseHandle);
711 }
712 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
713 goto ReleaseRDS;
714 }
715
716 /* Query reparse point information
717 * We only pay attention to mout point
718 */
720 FileName.Buffer = FileNameBuffer;
721 FileName.Length = sizeof(FileNameBuffer);
722 FileName.MaximumLength = sizeof(FileNameBuffer);
724 Status = ZwQueryDirectoryFile(Handle,
725 NULL,
726 NULL,
727 NULL,
729 &ReparsePointInformation,
732 TRUE,
733 &FileName,
734 FALSE);
735 if (!NT_SUCCESS(Status))
736 {
738 if (DatabaseHandle != 0)
739 {
740 TruncateRemoteDatabase(DatabaseHandle, 0);
741 CloseRemoteDatabase(DatabaseHandle);
742 }
743 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
744 goto ReleaseRDS;
745 }
746
747 /* If we failed to open the remote DB previously,
748 * retry this time allowing migration (and thus, creation if required)
749 */
750 if (DatabaseHandle == 0)
751 {
752 DatabaseHandle = OpenRemoteDatabase(DeviceInformation, TRUE);
753 if (DatabaseHandle == 0)
754 {
755 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
756 goto ReleaseRDS;
757 }
758 }
759
760 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
761
762 /* Reset all the references to our DB entries */
763 Offset = 0;
764 for (;;)
765 {
766 DatabaseEntry = GetRemoteDatabaseEntry(DatabaseHandle, Offset);
767 if (DatabaseEntry == NULL)
768 {
769 break;
770 }
771
772 DatabaseEntry->EntryReferences = 0;
773 Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
774 if (!NT_SUCCESS(Status))
775 {
776 FreePool(DatabaseEntry);
777 goto CloseReparse;
778 }
779
780 Offset += DatabaseEntry->EntrySize;
781 FreePool(DatabaseEntry);
782 }
783
784 /* Init string for QueryVolumeName call */
785 SymbolicName.MaximumLength = sizeof(SymbolicNameBuffer);
787 SymbolicName.Buffer = SymbolicNameBuffer;
788 Restart = TRUE;
789
790 /* Start looping on reparse points */
791 for (;;)
792 {
793 RtlCopyMemory(&SavedReparsePointInformation, &ReparsePointInformation, sizeof(FILE_REPARSE_POINT_INFORMATION));
794 Status = ZwQueryDirectoryFile(Handle,
795 NULL,
796 NULL,
797 NULL,
799 &ReparsePointInformation,
802 TRUE,
803 Restart ? &FileName : NULL,
804 Restart);
805 /* Restart only once */
806 if (Restart)
807 {
808 Restart = FALSE;
809 }
810 else
811 {
812 /* If we get the same one, we're done, bail out */
813 if (ReparsePointInformation.FileReference == SavedReparsePointInformation.FileReference &&
814 ReparsePointInformation.Tag == SavedReparsePointInformation.Tag)
815 {
816 break;
817 }
818 }
819
820 /* If querying failed, or if onloading, or if not returning mount points, bail out */
821 if (!NT_SUCCESS(Status) || Unloading || ReparsePointInformation.Tag != IO_REPARSE_TAG_MOUNT_POINT)
822 {
823 break;
824 }
825
826 /* Get the volume name associated to the mount point */
827 Status = QueryVolumeName(Handle, &ReparsePointInformation, 0, &SymbolicName, &VolumeName);
828 if (!NT_SUCCESS(Status))
829 {
830 continue;
831 }
832
833 /* Browse the DB to find the name */
834 Offset = 0;
835 for (;;)
836 {
837 UNICODE_STRING DbName;
838
839 DatabaseEntry = GetRemoteDatabaseEntry(DatabaseHandle, Offset);
840 if (DatabaseEntry == NULL)
841 {
842 break;
843 }
844
845 DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
846 DbName.Length = DbName.MaximumLength;
847 DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
848 /* Found, we're done! */
850 {
851 break;
852 }
853
854 Offset += DatabaseEntry->EntrySize;
855 FreePool(DatabaseEntry);
856 }
857
858 /* If we found the mount point.... */
859 if (DatabaseEntry != NULL)
860 {
861 /* If it was referenced, reference it once more and update to remote */
862 if (DatabaseEntry->EntryReferences)
863 {
864 ++DatabaseEntry->EntryReferences;
865 Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
866 if (!NT_SUCCESS(Status))
867 {
868 goto FreeDBEntry;
869 }
870
871 FreePool(DatabaseEntry);
872 }
873 else
874 {
875 /* Query the Unique ID associated to that mount point in case it changed */
876 KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
877 Status = QueryUniqueIdFromMaster(DeviceExtension, &SymbolicName, &UniqueId);
878 if (!NT_SUCCESS(Status))
879 {
880 /* If we failed doing so, reuse the old Unique ID and push it to master */
881 Status = WriteUniqueIdToMaster(DeviceExtension, DatabaseEntry);
882 if (!NT_SUCCESS(Status))
883 {
884 goto ReleaseDeviceLock;
885 }
886
887 /* And then, reference & write the entry */
888 ++DatabaseEntry->EntryReferences;
889 Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
890 if (!NT_SUCCESS(Status))
891 {
892 goto ReleaseDeviceLock;
893 }
894
895 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
896 FreePool(DatabaseEntry);
897 }
898 /* If the Unique ID didn't change */
899 else if (UniqueId->UniqueIdLength == DatabaseEntry->UniqueIdLength &&
900 RtlCompareMemory(UniqueId->UniqueId,
901 (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
902 UniqueId->UniqueIdLength) == UniqueId->UniqueIdLength)
903 {
904 /* Reference the entry, and update to remote */
905 ++DatabaseEntry->EntryReferences;
906 Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
907 if (!NT_SUCCESS(Status))
908 {
909 goto FreeUniqueId;
910 }
911
912 FreePool(UniqueId);
913 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
914 FreePool(DatabaseEntry);
915 }
916 /* Would, by chance, the Unique ID be present elsewhere? */
917 else if (IsUniqueIdPresent(DeviceExtension, DatabaseEntry))
918 {
919 /* Push the ID to master */
920 Status = WriteUniqueIdToMaster(DeviceExtension, DatabaseEntry);
921 if (!NT_SUCCESS(Status))
922 {
923 goto FreeUniqueId;
924 }
925
926 /* And then, reference & write the entry */
927 ++DatabaseEntry->EntryReferences;
928 Status = WriteRemoteDatabaseEntry(DatabaseHandle, Offset, DatabaseEntry);
929 if (!NT_SUCCESS(Status))
930 {
931 goto FreeUniqueId;
932 }
933
934 FreePool(UniqueId);
935 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
936 FreePool(DatabaseEntry);
937 }
938 else
939 {
940 /* OK, at that point, we're facing a totally unknown unique ID
941 * So, get rid of the old entry, and recreate a new one with
942 * the know unique ID
943 */
944 Status = DeleteRemoteDatabaseEntry(DatabaseHandle, Offset);
945 if (!NT_SUCCESS(Status))
946 {
947 goto FreeUniqueId;
948 }
949
950 FreePool(DatabaseEntry);
951 /* Allocate a new entry big enough */
952 DatabaseEntry = AllocatePool(UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY));
953 if (DatabaseEntry == NULL)
954 {
955 goto FreeUniqueId;
956 }
957
958 /* Configure it */
959 DatabaseEntry->EntrySize = UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY);
960 DatabaseEntry->EntryReferences = 1;
961 DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
962 DatabaseEntry->SymbolicNameLength = SymbolicName.Length;
963 DatabaseEntry->UniqueIdOffset = SymbolicName.Length + sizeof(DATABASE_ENTRY);
964 DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
965 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset), SymbolicName.Buffer, DatabaseEntry->SymbolicNameLength);
966 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
967
968 /* And write it remotely */
969 Status = AddRemoteDatabaseEntry(DatabaseHandle, DatabaseEntry);
970 if (!NT_SUCCESS(Status))
971 {
972 FreePool(DatabaseEntry);
973 goto FreeUniqueId;
974 }
975
976 FreePool(UniqueId);
977 FreePool(DatabaseEntry);
978 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
979 }
980 }
981 }
982 else
983 {
984 /* We failed finding it remotely
985 * So, let's allocate a new remote DB entry
986 */
987 KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
988 /* To be able to do so, we need the device Unique ID, ask master */
989 Status = QueryUniqueIdFromMaster(DeviceExtension, &SymbolicName, &UniqueId);
990 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
991 if (NT_SUCCESS(Status))
992 {
993 /* Allocate a new entry big enough */
994 DatabaseEntry = AllocatePool(UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY));
995 if (DatabaseEntry != NULL)
996 {
997 /* Configure it */
998 DatabaseEntry->EntrySize = UniqueId->UniqueIdLength + SymbolicName.Length + sizeof(DATABASE_ENTRY);
999 DatabaseEntry->EntryReferences = 1;
1000 DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
1001 DatabaseEntry->SymbolicNameLength = SymbolicName.Length;
1002 DatabaseEntry->UniqueIdOffset = SymbolicName.Length + sizeof(DATABASE_ENTRY);
1003 DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
1004 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset), SymbolicName.Buffer, DatabaseEntry->SymbolicNameLength);
1005 RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
1006
1007 /* And write it remotely */
1008 Status = AddRemoteDatabaseEntry(DatabaseHandle, DatabaseEntry);
1009 FreePool(DatabaseEntry);
1010 FreePool(UniqueId);
1011
1012 if (!NT_SUCCESS(Status))
1013 {
1014 goto FreeVolume;
1015 }
1016 }
1017 else
1018 {
1019 FreePool(UniqueId);
1020 }
1021 }
1022 }
1023
1024 /* Find info about the device associated associated with the mount point */
1025 KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1026 Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &ListDeviceInfo);
1027 if (!NT_SUCCESS(Status))
1028 {
1029 FailedFinding = TRUE;
1031 }
1032 else
1033 {
1034 /* Associate the device with the currrent DB */
1036 if (AssociatedDevice == NULL)
1037 {
1039 }
1040 else
1041 {
1042 AssociatedDevice->DeviceInformation = DeviceInformation;
1043 AssociatedDevice->String.Length = VolumeName.Length;
1044 AssociatedDevice->String.MaximumLength = VolumeName.MaximumLength;
1045 AssociatedDevice->String.Buffer = VolumeName.Buffer;
1046 InsertTailList(&ListDeviceInfo->AssociatedDevicesHead, &AssociatedDevice->AssociatedDevicesEntry);
1047 }
1048
1049 /* If we don't have to skip notifications, notify */
1050 if (!ListDeviceInfo->SkipNotifications)
1051 {
1052 PostOnlineNotification(DeviceExtension, &ListDeviceInfo->SymbolicName);
1053 }
1054 }
1055
1056 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1057 }
1058
1059 /* We don't need mount points any longer */
1060 ZwClose(Handle);
1061
1062 /* Look for the DB again */
1063 KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1064 for (Entry = DeviceExtension->DeviceListHead.Flink;
1065 Entry != &DeviceExtension->DeviceListHead;
1066 Entry = Entry->Flink)
1067 {
1068 ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
1069 if (ListDeviceInfo == DeviceInformation)
1070 {
1071 break;
1072 }
1073 }
1074
1075 if (Entry == &DeviceExtension->DeviceListHead)
1076 {
1077 ListDeviceInfo = NULL;
1078 }
1079
1080 /* Start the pruning loop */
1081 Offset = 0;
1082 for (;;)
1083 {
1084 /* Get the entry */
1085 DatabaseEntry = GetRemoteDatabaseEntry(DatabaseHandle, Offset);
1086 if (DatabaseEntry == NULL)
1087 {
1088 break;
1089 }
1090
1091 /* It's not referenced anylonger? Prune it */
1092 if (DatabaseEntry->EntryReferences == 0)
1093 {
1094 Status = DeleteRemoteDatabaseEntry(DatabaseHandle, Offset);
1095 if (!NT_SUCCESS(Status))
1096 {
1097 FreePool(DatabaseEntry);
1098 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1099 goto CloseRDB;
1100 }
1101 }
1102 /* Update the Unique IDs to reflect the changes we might have done previously */
1103 else
1104 {
1105 if (ListDeviceInfo != NULL)
1106 {
1107 UpdateReplicatedUniqueIds(ListDeviceInfo, DatabaseEntry);
1108 }
1109
1110 Offset += DatabaseEntry->EntrySize;
1111 }
1112
1113 FreePool(DatabaseEntry);
1114 }
1115
1116 /* We do have a DB now :-) */
1117 if (ListDeviceInfo != NULL && !FailedFinding)
1118 {
1119 DeviceInformation->NoDatabase = FALSE;
1120 }
1121
1122 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1123
1124 goto CloseRDB;
1125
1126FreeUniqueId:
1127 FreePool(UniqueId);
1128ReleaseDeviceLock:
1129 KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1130FreeDBEntry:
1131 FreePool(DatabaseEntry);
1132FreeVolume:
1134CloseReparse:
1135 ZwClose(Handle);
1136CloseRDB:
1137 CloseRemoteDatabase(DatabaseHandle);
1138ReleaseRDS:
1139 ReleaseRemoteDatabaseSemaphore(DeviceExtension);
1140 return;
1141}
WCHAR FileNameBuffer[MAX_PATH]
Definition: framewnd.c:225
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:897
@ 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:49
NTSTATUS FindDeviceInfo(IN PDEVICE_EXTENSION DeviceExtension, IN PUNICODE_STRING SymbolicName, IN BOOLEAN DeviceNameGiven, OUT PDEVICE_INFORMATION *DeviceInformation)
Definition: mountmgr.c:561
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:336

Referenced by MountMgrQueryDosVolumePaths(), and ReconcileThisDatabaseWithMaster().

◆ RedirectSavedLink()

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

Definition at line 717 of file symlink.c.

720{
721 PLIST_ENTRY NextEntry;
722 PSYMLINK_INFORMATION SymlinkInformation;
723
724 /* Find the link */
725 for (NextEntry = SavedLinkInformation->SymbolicLinksListHead.Flink;
726 NextEntry != &(SavedLinkInformation->SymbolicLinksListHead);
727 NextEntry = NextEntry->Flink)
728 {
729 SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
730
731 if (!RtlEqualUnicodeString(DosName, &(SymlinkInformation->Name), TRUE))
732 {
733 /* Delete old link */
735 /* Set its new location */
737
738 /* And remove it from the list (not valid any more) */
739 RemoveEntryList(&(SymlinkInformation->SymbolicLinksListEntry));
740 FreePool(SymlinkInformation->Name.Buffer);
741 FreePool(SymlinkInformation);
742
743 return TRUE;
744 }
745 }
746
747 return FALSE;
748}

Referenced by MountMgrMountedDeviceArrival().

◆ RegisterForTargetDeviceNotification()

VOID RegisterForTargetDeviceNotification ( IN PDEVICE_EXTENSION  DeviceExtension,
IN PDEVICE_INFORMATION  DeviceInformation 
)

Definition at line 250 of file notify.c.

252{
256
257 /* Get device object */
258 Status = IoGetDeviceObjectPointer(&(DeviceInformation->DeviceName),
260 &FileObject,
261 &DeviceObject);
262 if (!NT_SUCCESS(Status))
263 {
264 return;
265 }
266
267 /* And simply register for notifications */
269 0, FileObject,
270 DeviceExtension->DriverObject,
272 DeviceInformation,
273 &(DeviceInformation->TargetDeviceNotificationEntry));
274 if (!NT_SUCCESS(Status))
275 {
276 DeviceInformation->TargetDeviceNotificationEntry = NULL;
277 }
278
280
281 return;
282}
NTSTATUS NTAPI MountMgrTargetDeviceNotification(IN PVOID NotificationStructure, IN PVOID Context)
Definition: notify.c:206
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:346
@ 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 577 of file symlink.c.

579{
580 PLIST_ENTRY NextEntry;
581 PSAVED_LINK_INFORMATION SavedLinkInformation;
582
583 /* No saved links? Easy! */
584 if (IsListEmpty(&(DeviceExtension->SavedLinksListHead)))
585 {
586 return NULL;
587 }
588
589 /* Now, browse saved links */
590 for (NextEntry = DeviceExtension->SavedLinksListHead.Flink;
591 NextEntry != &(DeviceExtension->SavedLinksListHead);
592 NextEntry = NextEntry->Flink)
593 {
594 SavedLinkInformation = CONTAINING_RECORD(NextEntry,
596 SavedLinksListEntry);
597
598 /* Find the one that matches */
599 if (SavedLinkInformation->UniqueId->UniqueIdLength == UniqueId->UniqueIdLength)
600 {
601 if (RtlCompareMemory(SavedLinkInformation->UniqueId->UniqueId,
602 UniqueId->UniqueId,
603 UniqueId->UniqueIdLength) ==
604 UniqueId->UniqueIdLength)
605 {
606 /* Remove it and return it */
607 RemoveEntryList(&(SavedLinkInformation->SavedLinksListEntry));
608 return SavedLinkInformation;
609 }
610 }
611 }
612
613 /* None found (none removed) */
614 return NULL;
615}

Referenced by MountMgrMountedDeviceArrival().

◆ SendLinkCreated()

VOID SendLinkCreated ( IN PUNICODE_STRING  SymbolicName)

Definition at line 169 of file symlink.c.

170{
172 ULONG NameSize;
176
177 /* Get the device associated with the name */
180 &FileObject,
181 &DeviceObject);
182 if (!NT_SUCCESS(Status))
183 return;
184
185 /* Get attached device (will notify it) */
187
188 /* NameSize is the size of the whole MOUNTDEV_NAME structure */
189 NameSize = sizeof(USHORT) + SymbolicName->Length;
190 Name = AllocatePool(NameSize);
191 if (!Name)
192 goto Cleanup;
193
194 /* Initialize structure */
195 Name->NameLength = SymbolicName->Length;
197
198 /* Send the notification, using the new (Windows 2003+) IOCTL definition
199 * (with limited access) first. If this fails, the called driver may be
200 * for an older NT version, and so, we send again the notification using
201 * the old (Windows 2000) IOCTL definition (with any access). */
202 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_CREATED,
204 Name,
205 NameSize,
206 NULL,
207 0,
208 FileObject);
209 /* This one can fail, no one matters */
211#if (NTDDI_VERSION >= NTDDI_WS03)
212 /* Then, second one */
213 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_MOUNTDEV_LINK_CREATED_UNSECURE_DEPRECATED,
215 Name,
216 NameSize,
217 NULL,
218 0,
219 FileObject);
221#endif // (NTDDI_VERSION >= NTDDI_WS03)
222
223Cleanup:
224 if (Name)
225 FreePool(Name);
226
229
230 return;
231}
#define IOCTL_MOUNTDEV_LINK_CREATED
Definition: imports.h:104

Referenced by MountMgrCreatePointWorker(), and MountMgrMountedDeviceArrival().

◆ SendOnlineNotification()

VOID SendOnlineNotification ( IN PUNICODE_STRING  SymbolicName)

Definition at line 38 of file notify.c.

39{
43
44 /* Get device object */
49 if (!NT_SUCCESS(Status))
50 return;
51
52 /* And attached device object */
54
55 /* And send VOLUME_ONLINE */
56 Status = MountMgrSendSyncDeviceIoCtl(IOCTL_VOLUME_ONLINE,
58 NULL, 0,
59 NULL, 0,
62
65 return;
66}
#define IOCTL_VOLUME_ONLINE
Definition: ntddvol.h:63

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 174 of file notify.c.

175{
177
178 KeInitializeEvent(&(DeviceExtension->OnlineNotificationEvent), NotificationEvent, FALSE);
179
180 KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
181
182 /* Just wait all the worker are done */
183 if (DeviceExtension->OnlineNotificationCount != 1)
184 {
185 DeviceExtension->OnlineNotificationCount--;
186 KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
187
188 KeWaitForSingleObject(&(DeviceExtension->OnlineNotificationEvent),
189 Executive,
191 FALSE,
192 NULL);
193
194 KeAcquireSpinLock(&(DeviceExtension->WorkerLock), &OldIrql);
195 DeviceExtension->OnlineNotificationCount++;
196 }
197
198 KeReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
199}

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: d3dkmdt.h:49
static ULONG Timeout
Definition: ping.c:61
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163

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

◆ 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

◆ DeviceMount

UNICODE_STRING DeviceMount
extern

Definition at line 40 of file symlink.c.

Referenced by DriverEntry().

◆ DeviceObject

Definition at line 186 of file mntmgr.h.

◆ DosDevices

◆ DosDevicesMount

UNICODE_STRING DosDevicesMount
extern

Definition at line 41 of file symlink.c.

Referenced by DriverEntry(), and MountMgrUnload().

◆ DosGlobal

UNICODE_STRING DosGlobal
extern

Definition at line 45 of file symlink.c.

Referenced by CreateStringWithGlobal().

◆ DriverEntry

DRIVER_INITIALIZE DriverEntry

Definition at line 180 of file mntmgr.h.

◆ FileObject

◆ gdeviceObject

PDEVICE_OBJECT gdeviceObject
extern

Definition at line 35 of file mountmgr.c.

Referenced by DriverEntry(), and MountMgrUnload().

◆ Global

◆ InputBufferLength

◆ MountMgrDeviceControl

DRIVER_DISPATCH MountMgrDeviceControl

Definition at line 344 of file mntmgr.h.

Referenced by DriverEntry().

◆ OfflinePath

PWSTR OfflinePath
extern

Definition at line 32 of file database.c.

Referenced by IsOffline().

◆ OutputBufferLength

◆ ReparseIndex

UNICODE_STRING ReparseIndex
extern

Definition at line 49 of file symlink.c.

Referenced by OnlineMountedVolumes(), and ReconcileThisDatabaseWithMasterWorker().

◆ SafeVolumes

UNICODE_STRING SafeVolumes
extern

Definition at line 47 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 AddPartitionToDisk(), auxMessage(), BroadcastDriveLetterChange(), CheckFileSystemPage(), ChkdskVolume(), CreateNewVolumeName(), CreateNTOSInstallationsList(), DismountMain(), DismountPartition(), DismountVolume(), DoChecking(), DoFormatting(), 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(), FindNTOSInstallations(), FindVolCreateInTreeByVolume(), FltEnumerateVolumes(), FltGetDiskDeviceObject(), FltGetVolumeName(), FltGetVolumeProperties(), FormatDlgProcWorker(), FormatPartitionPage(), FormatVolume(), FsVolCommitOpsQueue(), GetNextUnformattedVolume(), InitDestinationPaths(), InitVolume(), InitVolumeDeviceName(), IsSupportedActivePartition(), LockOrUnlockVolume(), MMixerGetChannelCountLegacy(), MountVolume(), NtfsDiskRead(), NtfsFindAttribute(), NtfsFindAttributeHelper(), NtfsFindMftRecord(), NtfsFixupRecord(), NtfsInfoMain(), NtfsLookupFile(), NtfsMount(), NtfsOpen(), NtfsReadAttribute(), NtfsReadMftRecord(), OpenVolume(), PopFlushVolumes(), PopFlushVolumeWorker(), QueryMain(), RawMountVolume(), SelectFileSystemPage(), SetMain(), SetMountedDeviceValue(), SetMountedDeviceValues(), CAC97MiniportTopology::SetMultichannelVolume(), SmpCreatePagingFileOnAnyDrive(), SmpCreatePagingFileOnFixedDrive(), SmpCreateVolumeDescriptors(), SmpGetVolumeFreeSpace(), SmpSearchVolumeDescriptor(), StatisticsMain(), and WritePartitionsToDisk().