1ba447018SVictor Perevertkin /*
2ba447018SVictor Perevertkin * ReactOS kernel
3ba447018SVictor Perevertkin * Copyright (C) 2011-2012 ReactOS Team
4ba447018SVictor Perevertkin *
5ba447018SVictor Perevertkin * This program is free software; you can redistribute it and/or modify
6ba447018SVictor Perevertkin * it under the terms of the GNU General Public License as published by
7ba447018SVictor Perevertkin * the Free Software Foundation; either version 2 of the License, or
8ba447018SVictor Perevertkin * (at your option) any later version.
9ba447018SVictor Perevertkin *
10ba447018SVictor Perevertkin * This program is distributed in the hope that it will be useful,
11ba447018SVictor Perevertkin * but WITHOUT ANY WARRANTY; without even the implied warranty of
12ba447018SVictor Perevertkin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13ba447018SVictor Perevertkin * GNU General Public License for more details.
14ba447018SVictor Perevertkin *
15ba447018SVictor Perevertkin * You should have received a copy of the GNU General Public License
16ba447018SVictor Perevertkin * along with this program; if not, write to the Free Software
17ba447018SVictor Perevertkin * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18ba447018SVictor Perevertkin *
19ba447018SVictor Perevertkin * COPYRIGHT: See COPYING in the top level directory
20ba447018SVictor Perevertkin * PROJECT: ReactOS kernel
21ba447018SVictor Perevertkin * FILE: drivers/filesystem/mountmgr/device.c
22ba447018SVictor Perevertkin * PURPOSE: Mount Manager - Device Control
23ba447018SVictor Perevertkin * PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org)
24ba447018SVictor Perevertkin */
25ba447018SVictor Perevertkin
26ba447018SVictor Perevertkin #include "mntmgr.h"
27ba447018SVictor Perevertkin
28ba447018SVictor Perevertkin #define MAX_DEVICES 0x3E8 /* Matches 1000 devices */
29ba447018SVictor Perevertkin
30ba447018SVictor Perevertkin #define NDEBUG
31ba447018SVictor Perevertkin #include <debug.h>
32ba447018SVictor Perevertkin
33ba447018SVictor Perevertkin /*
34ba447018SVictor Perevertkin * @implemented
35ba447018SVictor Perevertkin */
36ba447018SVictor Perevertkin NTSTATUS
MountMgrChangeNotify(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)37ba447018SVictor Perevertkin MountMgrChangeNotify(IN PDEVICE_EXTENSION DeviceExtension,
38ba447018SVictor Perevertkin IN PIRP Irp)
39ba447018SVictor Perevertkin {
40ba447018SVictor Perevertkin KIRQL OldIrql;
41ba447018SVictor Perevertkin NTSTATUS Status;
42ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
43ba447018SVictor Perevertkin PMOUNTMGR_CHANGE_NOTIFY_INFO ChangeNotify;
44ba447018SVictor Perevertkin
45ba447018SVictor Perevertkin /* Get the I/O buffer */
46ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
47ba447018SVictor Perevertkin ChangeNotify = (PMOUNTMGR_CHANGE_NOTIFY_INFO)Irp->AssociatedIrp.SystemBuffer;
48ba447018SVictor Perevertkin
49ba447018SVictor Perevertkin /* Validate it */
50ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO) ||
51ba447018SVictor Perevertkin Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO))
52ba447018SVictor Perevertkin {
53ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
54ba447018SVictor Perevertkin }
55ba447018SVictor Perevertkin
56ba447018SVictor Perevertkin /* If epic number doesn't match, just return now one */
57ba447018SVictor Perevertkin if (DeviceExtension->EpicNumber != ChangeNotify->EpicNumber)
58ba447018SVictor Perevertkin {
59ba447018SVictor Perevertkin ChangeNotify->EpicNumber = DeviceExtension->EpicNumber;
60ba447018SVictor Perevertkin Irp->IoStatus.Information = sizeof(MOUNTMGR_CHANGE_NOTIFY_INFO);
61ba447018SVictor Perevertkin return STATUS_SUCCESS;
62ba447018SVictor Perevertkin }
63ba447018SVictor Perevertkin
64ba447018SVictor Perevertkin /* If IRP is to be canceled, forget about that */
65ba447018SVictor Perevertkin IoAcquireCancelSpinLock(&OldIrql);
66ba447018SVictor Perevertkin if (Irp->Cancel)
67ba447018SVictor Perevertkin {
68ba447018SVictor Perevertkin Status = STATUS_CANCELLED;
69ba447018SVictor Perevertkin }
70ba447018SVictor Perevertkin /* Otherwise queue the IRP to be notified with the next epic number change */
71ba447018SVictor Perevertkin else
72ba447018SVictor Perevertkin {
73ba447018SVictor Perevertkin InsertTailList(&(DeviceExtension->IrpListHead), &(Irp->Tail.Overlay.ListEntry));
74ba447018SVictor Perevertkin IoMarkIrpPending(Irp);
75ba447018SVictor Perevertkin IoSetCancelRoutine(Irp, MountMgrCancel);
76ba447018SVictor Perevertkin Status = STATUS_PENDING;
77ba447018SVictor Perevertkin }
78ba447018SVictor Perevertkin IoReleaseCancelSpinLock(OldIrql);
79ba447018SVictor Perevertkin
80ba447018SVictor Perevertkin return Status;
81ba447018SVictor Perevertkin }
82ba447018SVictor Perevertkin
83ba447018SVictor Perevertkin /*
84ba447018SVictor Perevertkin * @implemented
85ba447018SVictor Perevertkin */
86ba447018SVictor Perevertkin NTSTATUS
MountmgrWriteNoAutoMount(IN PDEVICE_EXTENSION DeviceExtension)87ba447018SVictor Perevertkin MountmgrWriteNoAutoMount(IN PDEVICE_EXTENSION DeviceExtension)
88ba447018SVictor Perevertkin {
89ba447018SVictor Perevertkin ULONG Value = DeviceExtension->NoAutoMount;
90ba447018SVictor Perevertkin
91ba447018SVictor Perevertkin return RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
92ba447018SVictor Perevertkin DeviceExtension->RegistryPath.Buffer,
93ba447018SVictor Perevertkin L"NoAutoMount",
94ba447018SVictor Perevertkin REG_DWORD,
95ba447018SVictor Perevertkin &Value,
96ba447018SVictor Perevertkin sizeof(Value));
97ba447018SVictor Perevertkin }
98ba447018SVictor Perevertkin
99ba447018SVictor Perevertkin /*
100ba447018SVictor Perevertkin * @implemented
101ba447018SVictor Perevertkin */
102ba447018SVictor Perevertkin NTSTATUS
MountMgrSetAutoMount(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)103ba447018SVictor Perevertkin MountMgrSetAutoMount(IN PDEVICE_EXTENSION DeviceExtension,
104ba447018SVictor Perevertkin IN PIRP Irp)
105ba447018SVictor Perevertkin {
106ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
107ba447018SVictor Perevertkin PMOUNTMGR_SET_AUTO_MOUNT SetState;
108ba447018SVictor Perevertkin
109ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
110ba447018SVictor Perevertkin
111ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_SET_AUTO_MOUNT))
112ba447018SVictor Perevertkin {
113ba447018SVictor Perevertkin Irp->IoStatus.Information = 0;
114ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
115ba447018SVictor Perevertkin }
116ba447018SVictor Perevertkin
117*5f263560SHermès Bélusca-Maïto /* Change the state only if there is a real difference
118*5f263560SHermès Bélusca-Maïto * with the user-provided NewState (normalized) */
119ba447018SVictor Perevertkin SetState = (PMOUNTMGR_SET_AUTO_MOUNT)Irp->AssociatedIrp.SystemBuffer;
120*5f263560SHermès Bélusca-Maïto if ((SetState->NewState != Enabled) == DeviceExtension->NoAutoMount)
121ba447018SVictor Perevertkin {
122ba447018SVictor Perevertkin Irp->IoStatus.Information = 0;
123ba447018SVictor Perevertkin return STATUS_SUCCESS;
124ba447018SVictor Perevertkin }
125ba447018SVictor Perevertkin
126*5f263560SHermès Bélusca-Maïto /* Set new state */
127*5f263560SHermès Bélusca-Maïto DeviceExtension->NoAutoMount = (SetState->NewState != Enabled);
128ba447018SVictor Perevertkin Irp->IoStatus.Information = 0;
129ba447018SVictor Perevertkin return MountmgrWriteNoAutoMount(DeviceExtension);
130ba447018SVictor Perevertkin }
131ba447018SVictor Perevertkin
132ba447018SVictor Perevertkin /*
133ba447018SVictor Perevertkin * @implemented
134ba447018SVictor Perevertkin */
135ba447018SVictor Perevertkin NTSTATUS
MountMgrQueryAutoMount(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)136ba447018SVictor Perevertkin MountMgrQueryAutoMount(IN PDEVICE_EXTENSION DeviceExtension,
137ba447018SVictor Perevertkin IN PIRP Irp)
138ba447018SVictor Perevertkin {
139ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
140ba447018SVictor Perevertkin PMOUNTMGR_QUERY_AUTO_MOUNT QueryState;
141ba447018SVictor Perevertkin
142ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
143ba447018SVictor Perevertkin
144ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_QUERY_AUTO_MOUNT))
145ba447018SVictor Perevertkin {
146ba447018SVictor Perevertkin Irp->IoStatus.Information = 0;
147ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
148ba447018SVictor Perevertkin }
149ba447018SVictor Perevertkin
150ba447018SVictor Perevertkin QueryState = (PMOUNTMGR_QUERY_AUTO_MOUNT)Irp->AssociatedIrp.SystemBuffer;
151ba447018SVictor Perevertkin QueryState->CurrentState = !DeviceExtension->NoAutoMount;
152ba447018SVictor Perevertkin Irp->IoStatus.Information = sizeof(MOUNTMGR_QUERY_AUTO_MOUNT);
153ba447018SVictor Perevertkin
154ba447018SVictor Perevertkin return STATUS_SUCCESS;
155ba447018SVictor Perevertkin }
156ba447018SVictor Perevertkin
157ba447018SVictor Perevertkin /*
158ba447018SVictor Perevertkin * @implemented
159ba447018SVictor Perevertkin */
160ba447018SVictor Perevertkin NTSTATUS
161ba447018SVictor Perevertkin NTAPI
ScrubRegistryRoutine(IN PWSTR ValueName,IN ULONG ValueType,IN PVOID ValueData,IN ULONG ValueLength,IN PVOID Context,IN PVOID EntryContext)162ba447018SVictor Perevertkin ScrubRegistryRoutine(IN PWSTR ValueName,
163ba447018SVictor Perevertkin IN ULONG ValueType,
164ba447018SVictor Perevertkin IN PVOID ValueData,
165ba447018SVictor Perevertkin IN ULONG ValueLength,
166ba447018SVictor Perevertkin IN PVOID Context,
167ba447018SVictor Perevertkin IN PVOID EntryContext)
168ba447018SVictor Perevertkin {
169ba447018SVictor Perevertkin NTSTATUS Status;
170ba447018SVictor Perevertkin PLIST_ENTRY NextEntry;
171ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInfo;
172ba447018SVictor Perevertkin PBOOLEAN Continue = EntryContext;
173ba447018SVictor Perevertkin PDEVICE_EXTENSION DeviceExtension = Context;
174ba447018SVictor Perevertkin
175ba447018SVictor Perevertkin if (ValueType != REG_BINARY)
176ba447018SVictor Perevertkin {
177ba447018SVictor Perevertkin return STATUS_SUCCESS;
178ba447018SVictor Perevertkin }
179ba447018SVictor Perevertkin
180ba447018SVictor Perevertkin /* Delete values for devices that don't have the matching unique ID */
181ba447018SVictor Perevertkin if (!IsListEmpty(&(DeviceExtension->DeviceListHead)))
182ba447018SVictor Perevertkin {
183ba447018SVictor Perevertkin for (NextEntry = DeviceExtension->DeviceListHead.Flink;
184ba447018SVictor Perevertkin NextEntry != &(DeviceExtension->DeviceListHead);
185ba447018SVictor Perevertkin NextEntry = NextEntry->Flink)
186ba447018SVictor Perevertkin {
187ba447018SVictor Perevertkin DeviceInfo = CONTAINING_RECORD(NextEntry,
188ba447018SVictor Perevertkin DEVICE_INFORMATION,
189ba447018SVictor Perevertkin DeviceListEntry);
190ba447018SVictor Perevertkin
191ba447018SVictor Perevertkin if (!DeviceInfo->UniqueId || DeviceInfo->UniqueId->UniqueIdLength != ValueLength)
192ba447018SVictor Perevertkin {
193ba447018SVictor Perevertkin continue;
194ba447018SVictor Perevertkin }
195ba447018SVictor Perevertkin
196ba447018SVictor Perevertkin if (RtlCompareMemory(DeviceInfo->UniqueId->UniqueId, ValueData, ValueLength) == ValueLength)
197ba447018SVictor Perevertkin {
198ba447018SVictor Perevertkin return STATUS_SUCCESS;
199ba447018SVictor Perevertkin }
200ba447018SVictor Perevertkin }
201ba447018SVictor Perevertkin }
202ba447018SVictor Perevertkin
203ba447018SVictor Perevertkin /* Wrong unique ID, scrub it */
204ba447018SVictor Perevertkin Status = RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE,
205ba447018SVictor Perevertkin DatabasePath,
206ba447018SVictor Perevertkin ValueName);
207ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
208ba447018SVictor Perevertkin {
209ba447018SVictor Perevertkin *Continue = TRUE;
210ba447018SVictor Perevertkin return STATUS_UNSUCCESSFUL;
211ba447018SVictor Perevertkin }
212ba447018SVictor Perevertkin
213ba447018SVictor Perevertkin *Continue = FALSE;
214ba447018SVictor Perevertkin return Status;
215ba447018SVictor Perevertkin }
216ba447018SVictor Perevertkin
217ba447018SVictor Perevertkin /*
218ba447018SVictor Perevertkin * @implemented
219ba447018SVictor Perevertkin */
220ba447018SVictor Perevertkin NTSTATUS
MountMgrScrubRegistry(IN PDEVICE_EXTENSION DeviceExtension)221ba447018SVictor Perevertkin MountMgrScrubRegistry(IN PDEVICE_EXTENSION DeviceExtension)
222ba447018SVictor Perevertkin {
223ba447018SVictor Perevertkin NTSTATUS Status;
224ba447018SVictor Perevertkin BOOLEAN Continue;
225ba447018SVictor Perevertkin RTL_QUERY_REGISTRY_TABLE QueryTable[2];
226ba447018SVictor Perevertkin
227ba447018SVictor Perevertkin do
228ba447018SVictor Perevertkin {
229ba447018SVictor Perevertkin RtlZeroMemory(QueryTable, sizeof(QueryTable));
230ba447018SVictor Perevertkin QueryTable[0].QueryRoutine = ScrubRegistryRoutine;
231ba447018SVictor Perevertkin QueryTable[0].EntryContext = &Continue;
232ba447018SVictor Perevertkin Continue = FALSE;
233ba447018SVictor Perevertkin
234ba447018SVictor Perevertkin Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
235ba447018SVictor Perevertkin DatabasePath,
236ba447018SVictor Perevertkin QueryTable,
237ba447018SVictor Perevertkin DeviceExtension,
238ba447018SVictor Perevertkin NULL);
239ba447018SVictor Perevertkin }
240ba447018SVictor Perevertkin while (Continue);
241ba447018SVictor Perevertkin
242ba447018SVictor Perevertkin return Status;
243ba447018SVictor Perevertkin }
244ba447018SVictor Perevertkin
245ba447018SVictor Perevertkin /*
246ba447018SVictor Perevertkin * @implemented
247ba447018SVictor Perevertkin */
248ba447018SVictor Perevertkin NTSTATUS
MountMgrCreatePoint(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)249ba447018SVictor Perevertkin MountMgrCreatePoint(IN PDEVICE_EXTENSION DeviceExtension,
250ba447018SVictor Perevertkin IN PIRP Irp)
251ba447018SVictor Perevertkin {
252ba447018SVictor Perevertkin ULONG MaxLength;
253ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
254ba447018SVictor Perevertkin PMOUNTMGR_CREATE_POINT_INPUT Point;
255ba447018SVictor Perevertkin UNICODE_STRING DeviceName, SymbolicName;
256ba447018SVictor Perevertkin
257ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
258ba447018SVictor Perevertkin
259ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_CREATE_POINT_INPUT))
260ba447018SVictor Perevertkin {
261ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
262ba447018SVictor Perevertkin }
263ba447018SVictor Perevertkin
264ba447018SVictor Perevertkin Point = (PMOUNTMGR_CREATE_POINT_INPUT)Irp->AssociatedIrp.SystemBuffer;
265ba447018SVictor Perevertkin
266ba447018SVictor Perevertkin MaxLength = MAX((Point->DeviceNameOffset + Point->DeviceNameLength),
267ba447018SVictor Perevertkin (Point->SymbolicLinkNameLength + Point->SymbolicLinkNameOffset));
268ba447018SVictor Perevertkin if (MaxLength > Stack->Parameters.DeviceIoControl.InputBufferLength)
269ba447018SVictor Perevertkin {
270ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
271ba447018SVictor Perevertkin }
272ba447018SVictor Perevertkin
273ba447018SVictor Perevertkin /* Get all the strings and call the worker */
274ba447018SVictor Perevertkin SymbolicName.Length = Point->SymbolicLinkNameLength;
275ba447018SVictor Perevertkin SymbolicName.MaximumLength = Point->SymbolicLinkNameLength;
276ba447018SVictor Perevertkin DeviceName.Length = Point->DeviceNameLength;
277ba447018SVictor Perevertkin DeviceName.MaximumLength = Point->DeviceNameLength;
278ba447018SVictor Perevertkin SymbolicName.Buffer = (PVOID)((ULONG_PTR)Point + Point->SymbolicLinkNameOffset);
279ba447018SVictor Perevertkin DeviceName.Buffer = (PVOID)((ULONG_PTR)Point + Point->DeviceNameOffset);
280ba447018SVictor Perevertkin
281ba447018SVictor Perevertkin return MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &DeviceName);
282ba447018SVictor Perevertkin }
283ba447018SVictor Perevertkin
284ba447018SVictor Perevertkin /*
285ba447018SVictor Perevertkin * @implemented
286ba447018SVictor Perevertkin */
287ba447018SVictor Perevertkin NTSTATUS
MountMgrCheckUnprocessedVolumes(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)288ba447018SVictor Perevertkin MountMgrCheckUnprocessedVolumes(IN PDEVICE_EXTENSION DeviceExtension,
289ba447018SVictor Perevertkin IN PIRP Irp)
290ba447018SVictor Perevertkin {
291ba447018SVictor Perevertkin PLIST_ENTRY NextEntry;
292ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation;
293ba447018SVictor Perevertkin NTSTATUS ArrivalStatus, Status = STATUS_SUCCESS;
294ba447018SVictor Perevertkin
295ba447018SVictor Perevertkin UNREFERENCED_PARAMETER(Irp);
296ba447018SVictor Perevertkin
297ba447018SVictor Perevertkin /* No offline volumes, nothing more to do */
298ba447018SVictor Perevertkin if (IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
299ba447018SVictor Perevertkin {
300ba447018SVictor Perevertkin KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
301ba447018SVictor Perevertkin return STATUS_SUCCESS;
302ba447018SVictor Perevertkin }
303ba447018SVictor Perevertkin
304ba447018SVictor Perevertkin KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
305ba447018SVictor Perevertkin
306ba447018SVictor Perevertkin /* Reactivate all the offline volumes */
307ba447018SVictor Perevertkin while (!IsListEmpty(&(DeviceExtension->OfflineDeviceListHead)))
308ba447018SVictor Perevertkin {
309ba447018SVictor Perevertkin NextEntry = RemoveHeadList(&(DeviceExtension->OfflineDeviceListHead));
310ba447018SVictor Perevertkin DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
311ba447018SVictor Perevertkin
312ba447018SVictor Perevertkin ArrivalStatus = MountMgrMountedDeviceArrival(DeviceExtension,
313ba447018SVictor Perevertkin &(DeviceInformation->SymbolicName),
314ba447018SVictor Perevertkin DeviceInformation->ManuallyRegistered);
315ba447018SVictor Perevertkin /* Then, remove them dead information */
316ba447018SVictor Perevertkin MountMgrFreeDeadDeviceInfo(DeviceInformation);
317ba447018SVictor Perevertkin
318ba447018SVictor Perevertkin if (NT_SUCCESS(Status))
319ba447018SVictor Perevertkin {
320ba447018SVictor Perevertkin Status = ArrivalStatus;
321ba447018SVictor Perevertkin }
322ba447018SVictor Perevertkin }
323ba447018SVictor Perevertkin
324ba447018SVictor Perevertkin return Status;
325ba447018SVictor Perevertkin }
326ba447018SVictor Perevertkin
327ba447018SVictor Perevertkin /*
328ba447018SVictor Perevertkin * @implemented
329ba447018SVictor Perevertkin */
330ba447018SVictor Perevertkin BOOLEAN
IsFtVolume(IN PUNICODE_STRING SymbolicName)331ba447018SVictor Perevertkin IsFtVolume(IN PUNICODE_STRING SymbolicName)
332ba447018SVictor Perevertkin {
333ba447018SVictor Perevertkin NTSTATUS Status;
334ba447018SVictor Perevertkin PFILE_OBJECT FileObject;
335ba447018SVictor Perevertkin PARTITION_INFORMATION PartitionInfo;
336ba447018SVictor Perevertkin PDEVICE_OBJECT DeviceObject, FileDeviceObject;
337ba447018SVictor Perevertkin
338ba447018SVictor Perevertkin /* Get device object */
339ba447018SVictor Perevertkin Status = IoGetDeviceObjectPointer(SymbolicName,
340ba447018SVictor Perevertkin FILE_READ_ATTRIBUTES,
341ba447018SVictor Perevertkin &FileObject,
342ba447018SVictor Perevertkin &DeviceObject);
343ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
344ba447018SVictor Perevertkin return FALSE;
345ba447018SVictor Perevertkin
346ba447018SVictor Perevertkin /* Get attached device */
347ba447018SVictor Perevertkin FileDeviceObject = FileObject->DeviceObject;
348ba447018SVictor Perevertkin DeviceObject = IoGetAttachedDeviceReference(FileDeviceObject);
349ba447018SVictor Perevertkin
350ba447018SVictor Perevertkin /* FT volume can't be removable */
351ba447018SVictor Perevertkin if (FileDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
352ba447018SVictor Perevertkin {
353ba447018SVictor Perevertkin ObDereferenceObject(DeviceObject);
354ba447018SVictor Perevertkin ObDereferenceObject(FileObject);
355ba447018SVictor Perevertkin return FALSE;
356ba447018SVictor Perevertkin }
357ba447018SVictor Perevertkin
358ba447018SVictor Perevertkin ObDereferenceObject(FileObject);
359ba447018SVictor Perevertkin
360ba447018SVictor Perevertkin /* Get partition information */
361ab0e04c8SHermès Bélusca-Maïto Status = MountMgrSendSyncDeviceIoCtl(IOCTL_DISK_GET_PARTITION_INFO,
362ba447018SVictor Perevertkin DeviceObject,
363ba447018SVictor Perevertkin NULL,
364ba447018SVictor Perevertkin 0,
365ba447018SVictor Perevertkin &PartitionInfo,
366ba447018SVictor Perevertkin sizeof(PartitionInfo),
367ab0e04c8SHermès Bélusca-Maïto NULL);
368ba447018SVictor Perevertkin
369ba447018SVictor Perevertkin ObDereferenceObject(DeviceObject);
370ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
371ba447018SVictor Perevertkin return FALSE;
372ba447018SVictor Perevertkin
373ba447018SVictor Perevertkin /* Check if this is a FT volume */
374ba447018SVictor Perevertkin return IsFTPartition(PartitionInfo.PartitionType);
375ba447018SVictor Perevertkin }
376ba447018SVictor Perevertkin
377ba447018SVictor Perevertkin /*
378ba447018SVictor Perevertkin * @implemented
379ba447018SVictor Perevertkin */
380ba447018SVictor Perevertkin VOID
ProcessSuggestedDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)381ba447018SVictor Perevertkin ProcessSuggestedDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
382ba447018SVictor Perevertkin {
383ba447018SVictor Perevertkin WCHAR NameBuffer[DRIVE_LETTER_LENGTH / sizeof(WCHAR)];
384ba447018SVictor Perevertkin PLIST_ENTRY NextEntry;
385ba447018SVictor Perevertkin UNICODE_STRING SymbolicName;
386ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation;
387ba447018SVictor Perevertkin
388ba447018SVictor Perevertkin /* No devices? Nothing to do! */
389ba447018SVictor Perevertkin if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
390ba447018SVictor Perevertkin {
391ba447018SVictor Perevertkin return;
392ba447018SVictor Perevertkin }
393ba447018SVictor Perevertkin
394ba447018SVictor Perevertkin /* For all the devices */
395ba447018SVictor Perevertkin for (NextEntry = DeviceExtension->DeviceListHead.Flink;
396ba447018SVictor Perevertkin NextEntry != &(DeviceExtension->DeviceListHead);
397ba447018SVictor Perevertkin NextEntry = NextEntry->Flink)
398ba447018SVictor Perevertkin {
399ba447018SVictor Perevertkin DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
400ba447018SVictor Perevertkin
401ba447018SVictor Perevertkin /* If no drive letter */
402ba447018SVictor Perevertkin if (DeviceInformation->SuggestedDriveLetter == (UCHAR)-1)
403ba447018SVictor Perevertkin {
404ba447018SVictor Perevertkin /* Ensure it has no entry yet */
405ba447018SVictor Perevertkin if (!HasDriveLetter(DeviceInformation) &&
406ba447018SVictor Perevertkin !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
407ba447018SVictor Perevertkin {
408ba447018SVictor Perevertkin /* And create one */
409ba447018SVictor Perevertkin CreateNoDriveLetterEntry(DeviceInformation->UniqueId);
410ba447018SVictor Perevertkin }
411ba447018SVictor Perevertkin
412ba447018SVictor Perevertkin DeviceInformation->SuggestedDriveLetter = 0;
413ba447018SVictor Perevertkin }
414ba447018SVictor Perevertkin /* Suggested letter & no entry */
415ba447018SVictor Perevertkin else if (DeviceInformation->SuggestedDriveLetter &&
416ba447018SVictor Perevertkin !HasNoDriveLetterEntry(DeviceInformation->UniqueId))
417ba447018SVictor Perevertkin {
418ba447018SVictor Perevertkin /* Just create a mount point */
419ba447018SVictor Perevertkin SymbolicName.Buffer = NameBuffer;
420ba447018SVictor Perevertkin RtlCopyMemory(NameBuffer, DosDevices.Buffer, DosDevices.Length);
421ba447018SVictor Perevertkin NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
422ba447018SVictor Perevertkin NameBuffer[COLON_POSITION] = L':';
423ba447018SVictor Perevertkin SymbolicName.Length =
424ba447018SVictor Perevertkin SymbolicName.MaximumLength = DRIVE_LETTER_LENGTH;
425ba447018SVictor Perevertkin
426ba447018SVictor Perevertkin MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &(DeviceInformation->DeviceName));
427ba447018SVictor Perevertkin }
428ba447018SVictor Perevertkin }
429ba447018SVictor Perevertkin }
430ba447018SVictor Perevertkin
431ba447018SVictor Perevertkin /*
432ba447018SVictor Perevertkin * @implemented
433ba447018SVictor Perevertkin */
434ba447018SVictor Perevertkin NTSTATUS
MountMgrNextDriveLetterWorker(IN PDEVICE_EXTENSION DeviceExtension,IN PUNICODE_STRING DeviceName,OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo)435ba447018SVictor Perevertkin MountMgrNextDriveLetterWorker(IN PDEVICE_EXTENSION DeviceExtension,
436ba447018SVictor Perevertkin IN PUNICODE_STRING DeviceName,
437ba447018SVictor Perevertkin OUT PMOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInfo)
438ba447018SVictor Perevertkin {
439ba447018SVictor Perevertkin NTSTATUS Status;
440ba447018SVictor Perevertkin UCHAR DriveLetter;
441ba447018SVictor Perevertkin PLIST_ENTRY NextEntry;
442ba447018SVictor Perevertkin PMOUNTDEV_UNIQUE_ID UniqueId;
443ba447018SVictor Perevertkin BOOLEAN Removable, GptDriveLetter;
444ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation;
445ba447018SVictor Perevertkin WCHAR NameBuffer[DRIVE_LETTER_LENGTH];
446ba447018SVictor Perevertkin PSYMLINK_INFORMATION SymlinkInformation;
447ba447018SVictor Perevertkin UNICODE_STRING TargetDeviceName, SymbolicName;
448ba447018SVictor Perevertkin
449ba447018SVictor Perevertkin /* First, process suggested letters */
450ba447018SVictor Perevertkin if (!DeviceExtension->ProcessedSuggestions)
451ba447018SVictor Perevertkin {
452ba447018SVictor Perevertkin ProcessSuggestedDriveLetters(DeviceExtension);
453ba447018SVictor Perevertkin DeviceExtension->ProcessedSuggestions = TRUE;
454ba447018SVictor Perevertkin }
455ba447018SVictor Perevertkin
456ba447018SVictor Perevertkin /* Then, get information about the device */
457ba447018SVictor Perevertkin Status = QueryDeviceInformation(DeviceName, &TargetDeviceName, NULL, &Removable, &GptDriveLetter, NULL, NULL, NULL);
458ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
459ba447018SVictor Perevertkin {
460ba447018SVictor Perevertkin return Status;
461ba447018SVictor Perevertkin }
462ba447018SVictor Perevertkin
463ba447018SVictor Perevertkin /* Ensure we have such device */
464ba447018SVictor Perevertkin NextEntry = DeviceExtension->DeviceListHead.Flink;
465ba447018SVictor Perevertkin while (NextEntry != &(DeviceExtension->DeviceListHead))
466ba447018SVictor Perevertkin {
467ba447018SVictor Perevertkin DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
468ba447018SVictor Perevertkin
469ba447018SVictor Perevertkin if (RtlCompareUnicodeString(&(DeviceInformation->DeviceName), &TargetDeviceName, TRUE) == 0)
470ba447018SVictor Perevertkin {
471ba447018SVictor Perevertkin break;
472ba447018SVictor Perevertkin }
473ba447018SVictor Perevertkin
474ba447018SVictor Perevertkin NextEntry = NextEntry->Flink;
475ba447018SVictor Perevertkin }
476ba447018SVictor Perevertkin
477ba447018SVictor Perevertkin if (NextEntry == &(DeviceExtension->DeviceListHead))
478ba447018SVictor Perevertkin {
479ba447018SVictor Perevertkin FreePool(TargetDeviceName.Buffer);
480ba447018SVictor Perevertkin return STATUS_OBJECT_NAME_NOT_FOUND;
481ba447018SVictor Perevertkin }
482ba447018SVictor Perevertkin
483*5f263560SHermès Bélusca-Maïto /* Now, assume we will assign a letter */
484ba447018SVictor Perevertkin DeviceInformation->LetterAssigned =
485ba447018SVictor Perevertkin DriveLetterInfo->DriveLetterWasAssigned = TRUE;
486ba447018SVictor Perevertkin
487ba447018SVictor Perevertkin /* Browse all the symlinks to check if there is already a drive letter */
488ba447018SVictor Perevertkin NextEntry = DeviceInformation->SymbolicLinksListHead.Flink;
489ba447018SVictor Perevertkin while (NextEntry != &(DeviceInformation->SymbolicLinksListHead))
490ba447018SVictor Perevertkin {
491ba447018SVictor Perevertkin SymlinkInformation = CONTAINING_RECORD(NextEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
492ba447018SVictor Perevertkin
493ba447018SVictor Perevertkin /* If this is a drive letter and it is online, forget about new drive letter */
494ba447018SVictor Perevertkin if (IsDriveLetter(&(SymlinkInformation->Name)) && SymlinkInformation->Online)
495ba447018SVictor Perevertkin {
496ba447018SVictor Perevertkin DriveLetterInfo->DriveLetterWasAssigned = FALSE;
497ba447018SVictor Perevertkin DriveLetterInfo->CurrentDriveLetter = (CHAR)SymlinkInformation->Name.Buffer[LETTER_POSITION];
498ba447018SVictor Perevertkin break;
499ba447018SVictor Perevertkin }
500ba447018SVictor Perevertkin
501ba447018SVictor Perevertkin NextEntry = NextEntry->Flink;
502ba447018SVictor Perevertkin }
503ba447018SVictor Perevertkin
504*5f263560SHermès Bélusca-Maïto /* If we didn't find a drive letter online, ensure this is not
505*5f263560SHermès Bélusca-Maïto * a no-drive entry by querying GPT attributes & database */
506ba447018SVictor Perevertkin if (NextEntry == &(DeviceInformation->SymbolicLinksListHead))
507ba447018SVictor Perevertkin {
508ba447018SVictor Perevertkin if (!GptDriveLetter || HasNoDriveLetterEntry(DeviceInformation->UniqueId))
509ba447018SVictor Perevertkin {
510ba447018SVictor Perevertkin DriveLetterInfo->DriveLetterWasAssigned = FALSE;
511ba447018SVictor Perevertkin DriveLetterInfo->CurrentDriveLetter = 0;
512ba447018SVictor Perevertkin goto Release;
513ba447018SVictor Perevertkin }
514ba447018SVictor Perevertkin }
515ba447018SVictor Perevertkin
516*5f263560SHermès Bélusca-Maïto /* If automount is disabled, and the device is not removable
517*5f263560SHermès Bélusca-Maïto * but needs a drive letter, don't assign one and bail out */
518*5f263560SHermès Bélusca-Maïto if (DeviceExtension->NoAutoMount && !Removable)
519ba447018SVictor Perevertkin {
520ba447018SVictor Perevertkin if (DriveLetterInfo->DriveLetterWasAssigned)
521ba447018SVictor Perevertkin {
522ba447018SVictor Perevertkin DriveLetterInfo->DriveLetterWasAssigned = FALSE;
523ba447018SVictor Perevertkin DriveLetterInfo->CurrentDriveLetter = 0;
524ba447018SVictor Perevertkin goto Release;
525ba447018SVictor Perevertkin }
526ba447018SVictor Perevertkin }
527ba447018SVictor Perevertkin
528*5f263560SHermès Bélusca-Maïto /* Stop now if we don't need to assign the drive a letter */
529ba447018SVictor Perevertkin if (!DriveLetterInfo->DriveLetterWasAssigned)
530ba447018SVictor Perevertkin goto Release;
531ba447018SVictor Perevertkin
532*5f263560SHermès Bélusca-Maïto /* Now everything is fine, begin drive letter assignment */
533ba447018SVictor Perevertkin
534ba447018SVictor Perevertkin if (RtlPrefixUnicodeString(&DeviceFloppy, &TargetDeviceName, TRUE))
535ba447018SVictor Perevertkin {
536ba447018SVictor Perevertkin /* If the device is a floppy, start with letter A */
537ba447018SVictor Perevertkin DriveLetter = 'A';
538ba447018SVictor Perevertkin }
539ba447018SVictor Perevertkin else if (RtlPrefixUnicodeString(&DeviceCdRom, &TargetDeviceName, TRUE))
540ba447018SVictor Perevertkin {
541ba447018SVictor Perevertkin /* If the device is a CD-ROM, start with letter D */
542ba447018SVictor Perevertkin DriveLetter = 'D';
543ba447018SVictor Perevertkin }
544ba447018SVictor Perevertkin else
545ba447018SVictor Perevertkin {
546ba447018SVictor Perevertkin /* Finally, if it's a disk, use C */
547ba447018SVictor Perevertkin DriveLetter = 'C';
548ba447018SVictor Perevertkin }
549ba447018SVictor Perevertkin
550ba447018SVictor Perevertkin /* We cannot set NO drive letter */
551ba447018SVictor Perevertkin ASSERT(DeviceInformation->SuggestedDriveLetter != (UCHAR)-1);
552ba447018SVictor Perevertkin
553ba447018SVictor Perevertkin /* If we don't have suggested letter but it's a FT volume, fail */
554ba447018SVictor Perevertkin if (!DeviceInformation->SuggestedDriveLetter && IsFtVolume(&(DeviceInformation->DeviceName)))
555ba447018SVictor Perevertkin {
556ba447018SVictor Perevertkin DriveLetterInfo->DriveLetterWasAssigned = FALSE;
557ba447018SVictor Perevertkin DriveLetterInfo->CurrentDriveLetter = 0;
558ba447018SVictor Perevertkin goto Release;
559ba447018SVictor Perevertkin }
560ba447018SVictor Perevertkin
561ba447018SVictor Perevertkin /* Prepare buffer */
562ba447018SVictor Perevertkin RtlCopyMemory(NameBuffer, DosDevices.Buffer, DosDevices.Length);
563ba447018SVictor Perevertkin NameBuffer[COLON_POSITION] = L':';
564ba447018SVictor Perevertkin SymbolicName.Buffer = NameBuffer;
565ba447018SVictor Perevertkin SymbolicName.Length =
566ba447018SVictor Perevertkin SymbolicName.MaximumLength = DRIVE_LETTER_LENGTH;
567ba447018SVictor Perevertkin
568ba447018SVictor Perevertkin /* It's all prepared, create mount point */
569ba447018SVictor Perevertkin if (DeviceInformation->SuggestedDriveLetter)
570ba447018SVictor Perevertkin {
571ba447018SVictor Perevertkin DriveLetterInfo->CurrentDriveLetter = DeviceInformation->SuggestedDriveLetter;
572ba447018SVictor Perevertkin NameBuffer[LETTER_POSITION] = DeviceInformation->SuggestedDriveLetter;
573ba447018SVictor Perevertkin
574ba447018SVictor Perevertkin Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
575ba447018SVictor Perevertkin if (NT_SUCCESS(Status))
576ba447018SVictor Perevertkin {
577ba447018SVictor Perevertkin goto Release;
578ba447018SVictor Perevertkin }
579ba447018SVictor Perevertkin }
580ba447018SVictor Perevertkin
581ba447018SVictor Perevertkin /* It failed with this letter... Try another one! */
582ba447018SVictor Perevertkin for (DriveLetterInfo->CurrentDriveLetter = DriveLetter;
583ba447018SVictor Perevertkin DriveLetterInfo->CurrentDriveLetter <= L'Z';
584ba447018SVictor Perevertkin DriveLetterInfo->CurrentDriveLetter++)
585ba447018SVictor Perevertkin {
586ba447018SVictor Perevertkin NameBuffer[LETTER_POSITION] = DriveLetterInfo->CurrentDriveLetter;
587ba447018SVictor Perevertkin
588ba447018SVictor Perevertkin Status = MountMgrCreatePointWorker(DeviceExtension, &SymbolicName, &TargetDeviceName);
589ba447018SVictor Perevertkin if (NT_SUCCESS(Status))
590ba447018SVictor Perevertkin {
591ba447018SVictor Perevertkin break;
592ba447018SVictor Perevertkin }
593ba447018SVictor Perevertkin }
594ba447018SVictor Perevertkin
595ba447018SVictor Perevertkin /* We failed setting a letter */
596ba447018SVictor Perevertkin if (DriveLetterInfo->CurrentDriveLetter > L'Z')
597ba447018SVictor Perevertkin {
598ba447018SVictor Perevertkin DriveLetterInfo->DriveLetterWasAssigned = FALSE;
599ba447018SVictor Perevertkin DriveLetterInfo->CurrentDriveLetter = 0;
600ba447018SVictor Perevertkin
601ba447018SVictor Perevertkin /* Try at least to add a no drive letter entry */
602ba447018SVictor Perevertkin Status = QueryDeviceInformation(&TargetDeviceName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
603ba447018SVictor Perevertkin if (NT_SUCCESS(Status))
604ba447018SVictor Perevertkin {
605ba447018SVictor Perevertkin CreateNoDriveLetterEntry(UniqueId);
606ba447018SVictor Perevertkin FreePool(UniqueId);
607ba447018SVictor Perevertkin }
608ba447018SVictor Perevertkin }
609ba447018SVictor Perevertkin
610ba447018SVictor Perevertkin Release:
611ba447018SVictor Perevertkin FreePool(TargetDeviceName.Buffer);
612ba447018SVictor Perevertkin
613ba447018SVictor Perevertkin return STATUS_SUCCESS;
614ba447018SVictor Perevertkin }
615ba447018SVictor Perevertkin
616ba447018SVictor Perevertkin
617ba447018SVictor Perevertkin /*
618ba447018SVictor Perevertkin * @implemented
619ba447018SVictor Perevertkin */
620ba447018SVictor Perevertkin NTSTATUS
MountMgrNextDriveLetter(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)621ba447018SVictor Perevertkin MountMgrNextDriveLetter(IN PDEVICE_EXTENSION DeviceExtension,
622ba447018SVictor Perevertkin IN PIRP Irp)
623ba447018SVictor Perevertkin {
624ba447018SVictor Perevertkin NTSTATUS Status;
625ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
626ba447018SVictor Perevertkin UNICODE_STRING DeviceName;
627ba447018SVictor Perevertkin PMOUNTMGR_DRIVE_LETTER_TARGET DriveLetterTarget;
628ba447018SVictor Perevertkin MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
629ba447018SVictor Perevertkin
630ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
631ba447018SVictor Perevertkin
632ba447018SVictor Perevertkin /* Validate input */
633ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_TARGET) ||
634ba447018SVictor Perevertkin Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION))
635ba447018SVictor Perevertkin {
636ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
637ba447018SVictor Perevertkin }
638ba447018SVictor Perevertkin
639ba447018SVictor Perevertkin DriveLetterTarget = (PMOUNTMGR_DRIVE_LETTER_TARGET)Irp->AssociatedIrp.SystemBuffer;
640ba447018SVictor Perevertkin if (DriveLetterTarget->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
641ba447018SVictor Perevertkin {
642ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
643ba447018SVictor Perevertkin }
644ba447018SVictor Perevertkin
645ba447018SVictor Perevertkin /* Call the worker */
646ba447018SVictor Perevertkin DeviceName.Buffer = DriveLetterTarget->DeviceName;
647ba447018SVictor Perevertkin DeviceName.Length =
648ba447018SVictor Perevertkin DeviceName.MaximumLength = DriveLetterTarget->DeviceNameLength;
649ba447018SVictor Perevertkin
650ba447018SVictor Perevertkin Status = MountMgrNextDriveLetterWorker(DeviceExtension, &DeviceName,
651ba447018SVictor Perevertkin &DriveLetterInformation);
652ba447018SVictor Perevertkin if (NT_SUCCESS(Status))
653ba447018SVictor Perevertkin {
654ba447018SVictor Perevertkin *(PMOUNTMGR_DRIVE_LETTER_INFORMATION)Irp->AssociatedIrp.SystemBuffer =
655ba447018SVictor Perevertkin DriveLetterInformation;
656ba447018SVictor Perevertkin Irp->IoStatus.Information = sizeof(MOUNTMGR_DRIVE_LETTER_INFORMATION);
657ba447018SVictor Perevertkin }
658ba447018SVictor Perevertkin
659ba447018SVictor Perevertkin return Status;
660ba447018SVictor Perevertkin }
661ba447018SVictor Perevertkin
662ba447018SVictor Perevertkin /*
663ba447018SVictor Perevertkin * @implemented
664ba447018SVictor Perevertkin */
665ba447018SVictor Perevertkin NTSTATUS
666ba447018SVictor Perevertkin NTAPI
MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName,IN ULONG ValueType,IN PVOID ValueData,IN ULONG ValueLength,IN PVOID Context,IN PVOID EntryContext)667ba447018SVictor Perevertkin MountMgrQuerySystemVolumeNameQueryRoutine(IN PWSTR ValueName,
668ba447018SVictor Perevertkin IN ULONG ValueType,
669ba447018SVictor Perevertkin IN PVOID ValueData,
670ba447018SVictor Perevertkin IN ULONG ValueLength,
671ba447018SVictor Perevertkin IN PVOID Context,
672ba447018SVictor Perevertkin IN PVOID EntryContext)
673ba447018SVictor Perevertkin {
674ba447018SVictor Perevertkin UNICODE_STRING ValueString;
675ba447018SVictor Perevertkin PUNICODE_STRING SystemVolumeName;
676ba447018SVictor Perevertkin
677ba447018SVictor Perevertkin UNREFERENCED_PARAMETER(ValueName);
678ba447018SVictor Perevertkin UNREFERENCED_PARAMETER(ValueLength);
679ba447018SVictor Perevertkin UNREFERENCED_PARAMETER(EntryContext);
680ba447018SVictor Perevertkin
681ba447018SVictor Perevertkin if (ValueType != REG_SZ)
682ba447018SVictor Perevertkin {
683ba447018SVictor Perevertkin return STATUS_SUCCESS;
684ba447018SVictor Perevertkin }
685ba447018SVictor Perevertkin
686ba447018SVictor Perevertkin RtlInitUnicodeString(&ValueString, ValueData);
687ba447018SVictor Perevertkin SystemVolumeName = Context;
688ba447018SVictor Perevertkin
689ba447018SVictor Perevertkin /* Return a string containing system volume name */
690ba447018SVictor Perevertkin SystemVolumeName->Length = ValueString.Length;
691ba447018SVictor Perevertkin SystemVolumeName->MaximumLength = ValueString.Length + sizeof(WCHAR);
692ba447018SVictor Perevertkin SystemVolumeName->Buffer = AllocatePool(SystemVolumeName->MaximumLength);
693ba447018SVictor Perevertkin if (SystemVolumeName->Buffer)
694ba447018SVictor Perevertkin {
695ba447018SVictor Perevertkin RtlCopyMemory(SystemVolumeName->Buffer, ValueData, ValueString.Length);
696ba447018SVictor Perevertkin SystemVolumeName->Buffer[ValueString.Length / sizeof(WCHAR)] = UNICODE_NULL;
697ba447018SVictor Perevertkin }
698ba447018SVictor Perevertkin
699ba447018SVictor Perevertkin return STATUS_SUCCESS;
700ba447018SVictor Perevertkin
701ba447018SVictor Perevertkin }
702ba447018SVictor Perevertkin
703ba447018SVictor Perevertkin /*
704ba447018SVictor Perevertkin * @implemented
705ba447018SVictor Perevertkin */
706ba447018SVictor Perevertkin NTSTATUS
MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName)707ba447018SVictor Perevertkin MountMgrQuerySystemVolumeName(OUT PUNICODE_STRING SystemVolumeName)
708ba447018SVictor Perevertkin {
709ba447018SVictor Perevertkin RTL_QUERY_REGISTRY_TABLE QueryTable[2];
710ba447018SVictor Perevertkin
711ba447018SVictor Perevertkin RtlZeroMemory(QueryTable, sizeof(QueryTable));
712ba447018SVictor Perevertkin QueryTable[0].QueryRoutine = MountMgrQuerySystemVolumeNameQueryRoutine;
713ba447018SVictor Perevertkin QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
714ba447018SVictor Perevertkin QueryTable[0].Name = L"SystemPartition";
715ba447018SVictor Perevertkin
716ba447018SVictor Perevertkin SystemVolumeName->Buffer = NULL;
717ba447018SVictor Perevertkin
718ba447018SVictor Perevertkin RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
719ba447018SVictor Perevertkin L"\\Registry\\Machine\\System\\Setup",
720ba447018SVictor Perevertkin QueryTable,
721ba447018SVictor Perevertkin SystemVolumeName,
722ba447018SVictor Perevertkin NULL);
723ba447018SVictor Perevertkin
724ba447018SVictor Perevertkin if (SystemVolumeName->Buffer)
725ba447018SVictor Perevertkin {
726ba447018SVictor Perevertkin return STATUS_SUCCESS;
727ba447018SVictor Perevertkin }
728ba447018SVictor Perevertkin
729ba447018SVictor Perevertkin return STATUS_UNSUCCESSFUL;
730ba447018SVictor Perevertkin }
731ba447018SVictor Perevertkin
732ba447018SVictor Perevertkin /*
733ba447018SVictor Perevertkin * @implemented
734ba447018SVictor Perevertkin */
735ba447018SVictor Perevertkin VOID
MountMgrAssignDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)736ba447018SVictor Perevertkin MountMgrAssignDriveLetters(IN PDEVICE_EXTENSION DeviceExtension)
737ba447018SVictor Perevertkin {
738ba447018SVictor Perevertkin NTSTATUS Status;
739ba447018SVictor Perevertkin PLIST_ENTRY NextEntry;
740ba447018SVictor Perevertkin UNICODE_STRING SystemVolumeName;
741ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation;
742ba447018SVictor Perevertkin MOUNTMGR_DRIVE_LETTER_INFORMATION DriveLetterInformation;
743ba447018SVictor Perevertkin
744ba447018SVictor Perevertkin /* First, get system volume name */
745ba447018SVictor Perevertkin Status = MountMgrQuerySystemVolumeName(&SystemVolumeName);
746ba447018SVictor Perevertkin
747ba447018SVictor Perevertkin /* If there are no device, it's all done */
748ba447018SVictor Perevertkin if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
749ba447018SVictor Perevertkin {
750ba447018SVictor Perevertkin if (NT_SUCCESS(Status))
751ba447018SVictor Perevertkin {
752ba447018SVictor Perevertkin FreePool(SystemVolumeName.Buffer);
753ba447018SVictor Perevertkin }
754ba447018SVictor Perevertkin
755ba447018SVictor Perevertkin return;
756ba447018SVictor Perevertkin }
757ba447018SVictor Perevertkin
758ba447018SVictor Perevertkin /* Now, for all the devices... */
759ba447018SVictor Perevertkin for (NextEntry = DeviceExtension->DeviceListHead.Flink;
760ba447018SVictor Perevertkin NextEntry != &(DeviceExtension->DeviceListHead);
761ba447018SVictor Perevertkin NextEntry = NextEntry->Flink)
762ba447018SVictor Perevertkin {
763ba447018SVictor Perevertkin DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
764ba447018SVictor Perevertkin
765ba447018SVictor Perevertkin /* If the device doesn't have a letter assigned, do it! */
766ba447018SVictor Perevertkin if (!DeviceInformation->LetterAssigned)
767ba447018SVictor Perevertkin {
768ba447018SVictor Perevertkin MountMgrNextDriveLetterWorker(DeviceExtension,
769ba447018SVictor Perevertkin &(DeviceInformation->DeviceName),
770ba447018SVictor Perevertkin &DriveLetterInformation);
771ba447018SVictor Perevertkin }
772ba447018SVictor Perevertkin
773*5f263560SHermès Bélusca-Maïto /* If it's the system volume */
774ba447018SVictor Perevertkin if (NT_SUCCESS(Status) && RtlEqualUnicodeString(&SystemVolumeName, &(DeviceInformation->DeviceName), TRUE))
775ba447018SVictor Perevertkin {
776ba447018SVictor Perevertkin /* Keep track of it */
777ba447018SVictor Perevertkin DeviceExtension->DriveLetterData = AllocatePool(DeviceInformation->UniqueId->UniqueIdLength +
778ba447018SVictor Perevertkin sizeof(MOUNTDEV_UNIQUE_ID));
779ba447018SVictor Perevertkin if (DeviceExtension->DriveLetterData)
780ba447018SVictor Perevertkin {
781ba447018SVictor Perevertkin RtlCopyMemory(DeviceExtension->DriveLetterData,
782ba447018SVictor Perevertkin DeviceInformation->UniqueId,
783ba447018SVictor Perevertkin DeviceInformation->UniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
784ba447018SVictor Perevertkin }
785ba447018SVictor Perevertkin
786*5f263560SHermès Bélusca-Maïto /* Ensure it gets mounted if automount is disabled */
787*5f263560SHermès Bélusca-Maïto if (DeviceExtension->NoAutoMount)
788ba447018SVictor Perevertkin {
789*5f263560SHermès Bélusca-Maïto /* Temporarily re-enable automount for the
790*5f263560SHermès Bélusca-Maïto * worker to mount and set a drive letter */
791*5f263560SHermès Bélusca-Maïto DeviceExtension->NoAutoMount = FALSE;
792ba447018SVictor Perevertkin
793ba447018SVictor Perevertkin MountMgrNextDriveLetterWorker(DeviceExtension,
794ba447018SVictor Perevertkin &(DeviceInformation->DeviceName),
795ba447018SVictor Perevertkin &DriveLetterInformation);
796ba447018SVictor Perevertkin
797*5f263560SHermès Bélusca-Maïto /* And re-disable automount */
798*5f263560SHermès Bélusca-Maïto DeviceExtension->NoAutoMount = TRUE;
799ba447018SVictor Perevertkin }
800ba447018SVictor Perevertkin }
801ba447018SVictor Perevertkin }
802ba447018SVictor Perevertkin
803ba447018SVictor Perevertkin if (NT_SUCCESS(Status))
804ba447018SVictor Perevertkin {
805ba447018SVictor Perevertkin FreePool(SystemVolumeName.Buffer);
806ba447018SVictor Perevertkin }
807ba447018SVictor Perevertkin }
808ba447018SVictor Perevertkin
809ba447018SVictor Perevertkin /*
810ba447018SVictor Perevertkin * @implemented
811ba447018SVictor Perevertkin */
812ba447018SVictor Perevertkin NTSTATUS
MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)813ba447018SVictor Perevertkin MountMgrQueryDosVolumePath(IN PDEVICE_EXTENSION DeviceExtension,
814ba447018SVictor Perevertkin IN PIRP Irp)
815ba447018SVictor Perevertkin {
816ba447018SVictor Perevertkin NTSTATUS Status;
817ba447018SVictor Perevertkin ULONG DevicesFound;
818ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
819ba447018SVictor Perevertkin PLIST_ENTRY SymlinksEntry;
820ba447018SVictor Perevertkin UNICODE_STRING SymbolicName;
821ba447018SVictor Perevertkin PMOUNTMGR_TARGET_NAME Target;
822ba447018SVictor Perevertkin PWSTR DeviceString, OldBuffer;
823ba447018SVictor Perevertkin USHORT DeviceLength, OldLength;
824ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation;
825ba447018SVictor Perevertkin PSYMLINK_INFORMATION SymlinkInformation;
826ba447018SVictor Perevertkin PASSOCIATED_DEVICE_ENTRY AssociatedDevice;
827ba447018SVictor Perevertkin
828ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
829ba447018SVictor Perevertkin
830ba447018SVictor Perevertkin /* Validate input size */
831ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
832ba447018SVictor Perevertkin {
833ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
834ba447018SVictor Perevertkin }
835ba447018SVictor Perevertkin
836ba447018SVictor Perevertkin /* Ensure we have received UNICODE_STRING */
837ba447018SVictor Perevertkin Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
838ba447018SVictor Perevertkin if (Target->DeviceNameLength & 1)
839ba447018SVictor Perevertkin {
840ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
841ba447018SVictor Perevertkin }
842ba447018SVictor Perevertkin
843ba447018SVictor Perevertkin /* Validate the entry structure size */
844f9f5a787SVictor Perevertkin if ((FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceNameLength) + Target->DeviceNameLength) >
845f9f5a787SVictor Perevertkin Stack->Parameters.DeviceIoControl.InputBufferLength)
846ba447018SVictor Perevertkin {
847ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
848ba447018SVictor Perevertkin }
849ba447018SVictor Perevertkin
850ba447018SVictor Perevertkin /* Ensure we can at least return needed size */
851ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
852ba447018SVictor Perevertkin {
853ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
854ba447018SVictor Perevertkin }
855ba447018SVictor Perevertkin
856ba447018SVictor Perevertkin /* Construct string for query */
857ba447018SVictor Perevertkin SymbolicName.Length = Target->DeviceNameLength;
858f9f5a787SVictor Perevertkin SymbolicName.MaximumLength = Target->DeviceNameLength;
859ba447018SVictor Perevertkin SymbolicName.Buffer = Target->DeviceName;
860ba447018SVictor Perevertkin
861ba447018SVictor Perevertkin /* Find device with our info */
862ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
863ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
864ba447018SVictor Perevertkin {
865ba447018SVictor Perevertkin return Status;
866ba447018SVictor Perevertkin }
867ba447018SVictor Perevertkin
868ba447018SVictor Perevertkin DeviceLength = 0;
869ba447018SVictor Perevertkin DeviceString = NULL;
870ba447018SVictor Perevertkin DevicesFound = 0;
871ba447018SVictor Perevertkin
872ba447018SVictor Perevertkin /* Try to find associated device info */
873ba447018SVictor Perevertkin while (TRUE)
874ba447018SVictor Perevertkin {
875ba447018SVictor Perevertkin for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
876ba447018SVictor Perevertkin SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
877ba447018SVictor Perevertkin SymlinksEntry = SymlinksEntry->Flink)
878ba447018SVictor Perevertkin {
879ba447018SVictor Perevertkin SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
880ba447018SVictor Perevertkin
881ba447018SVictor Perevertkin /* Try to find with drive letter */
882ba447018SVictor Perevertkin if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
883ba447018SVictor Perevertkin {
884ba447018SVictor Perevertkin break;
885ba447018SVictor Perevertkin }
886ba447018SVictor Perevertkin }
887ba447018SVictor Perevertkin
888ba447018SVictor Perevertkin /* We didn't find, break */
889ba447018SVictor Perevertkin if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead))
890ba447018SVictor Perevertkin {
891f9f5a787SVictor Perevertkin return STATUS_NOT_FOUND;
892ba447018SVictor Perevertkin }
893ba447018SVictor Perevertkin
894ba447018SVictor Perevertkin /* It doesn't have associated device, go to fallback method */
895ba447018SVictor Perevertkin if (IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
896ba447018SVictor Perevertkin {
897ba447018SVictor Perevertkin goto TryWithVolumeName;
898ba447018SVictor Perevertkin }
899ba447018SVictor Perevertkin
900ba447018SVictor Perevertkin /* Create a string with the information about the device */
901ba447018SVictor Perevertkin AssociatedDevice = CONTAINING_RECORD(&(DeviceInformation->SymbolicLinksListHead), ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
902ba447018SVictor Perevertkin OldLength = DeviceLength;
903ba447018SVictor Perevertkin OldBuffer = DeviceString;
904ba447018SVictor Perevertkin DeviceLength += AssociatedDevice->String.Length;
905ba447018SVictor Perevertkin DeviceString = AllocatePool(DeviceLength);
906ba447018SVictor Perevertkin if (!DeviceString)
907ba447018SVictor Perevertkin {
908ba447018SVictor Perevertkin if (OldBuffer)
909ba447018SVictor Perevertkin {
910ba447018SVictor Perevertkin FreePool(OldBuffer);
911ba447018SVictor Perevertkin }
912ba447018SVictor Perevertkin
913ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
914ba447018SVictor Perevertkin }
915ba447018SVictor Perevertkin
916ba447018SVictor Perevertkin /* Store our info and previous if any */
917ba447018SVictor Perevertkin RtlCopyMemory(DeviceString, AssociatedDevice->String.Buffer, AssociatedDevice->String.Length);
918ba447018SVictor Perevertkin if (OldBuffer)
919ba447018SVictor Perevertkin {
920ba447018SVictor Perevertkin RtlCopyMemory(&DeviceString[AssociatedDevice->String.Length / sizeof(WCHAR)], OldBuffer, OldLength);
921ba447018SVictor Perevertkin FreePool(OldBuffer);
922ba447018SVictor Perevertkin }
923ba447018SVictor Perevertkin
924ba447018SVictor Perevertkin /* Count and continue looking */
925ba447018SVictor Perevertkin ++DevicesFound;
926ba447018SVictor Perevertkin DeviceInformation = AssociatedDevice->DeviceInformation;
927ba447018SVictor Perevertkin
928ba447018SVictor Perevertkin /* If too many devices, try another way */
929ba447018SVictor Perevertkin if (DevicesFound > MAX_DEVICES) /* 1000 */
930ba447018SVictor Perevertkin {
931ba447018SVictor Perevertkin goto TryWithVolumeName;
932ba447018SVictor Perevertkin }
933ba447018SVictor Perevertkin }
934ba447018SVictor Perevertkin
935ba447018SVictor Perevertkin /* Reallocate our string, so that we can prepend disk letter */
936ba447018SVictor Perevertkin OldBuffer = DeviceString;
937ba447018SVictor Perevertkin OldLength = DeviceLength;
938ba447018SVictor Perevertkin DeviceLength += 2 * sizeof(WCHAR);
939ba447018SVictor Perevertkin DeviceString = AllocatePool(DeviceLength);
940ba447018SVictor Perevertkin if (!DeviceString)
941ba447018SVictor Perevertkin {
942ba447018SVictor Perevertkin if (OldBuffer)
943ba447018SVictor Perevertkin {
944ba447018SVictor Perevertkin FreePool(OldBuffer);
945ba447018SVictor Perevertkin }
946ba447018SVictor Perevertkin
947ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
948ba447018SVictor Perevertkin }
949ba447018SVictor Perevertkin
950ba447018SVictor Perevertkin /* Get the letter */
951ba447018SVictor Perevertkin DeviceString[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
952ba447018SVictor Perevertkin DeviceString[1] = L':';
953ba447018SVictor Perevertkin
954ba447018SVictor Perevertkin /* And copy the rest */
955ba447018SVictor Perevertkin if (OldBuffer)
956ba447018SVictor Perevertkin {
957ba447018SVictor Perevertkin RtlCopyMemory(&DeviceString[2], OldBuffer, OldLength);
958ba447018SVictor Perevertkin FreePool(OldBuffer);
959ba447018SVictor Perevertkin }
960ba447018SVictor Perevertkin
961ba447018SVictor Perevertkin TryWithVolumeName:
962ba447018SVictor Perevertkin /* If we didn't find anything, try differently */
963ba447018SVictor Perevertkin if (DeviceLength < 2 * sizeof(WCHAR) || DeviceString[1] != L':')
964ba447018SVictor Perevertkin {
965ba447018SVictor Perevertkin if (DeviceString)
966ba447018SVictor Perevertkin {
967ba447018SVictor Perevertkin FreePool(DeviceString);
968ba447018SVictor Perevertkin DeviceLength = 0;
969ba447018SVictor Perevertkin }
970ba447018SVictor Perevertkin
971ba447018SVictor Perevertkin /* Try to find a volume name matching */
972ba447018SVictor Perevertkin for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
973ba447018SVictor Perevertkin SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
974ba447018SVictor Perevertkin SymlinksEntry = SymlinksEntry->Flink)
975ba447018SVictor Perevertkin {
976ba447018SVictor Perevertkin SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
977ba447018SVictor Perevertkin
978ba447018SVictor Perevertkin if (MOUNTMGR_IS_VOLUME_NAME(&SymlinkInformation->Name))
979ba447018SVictor Perevertkin {
980ba447018SVictor Perevertkin break;
981ba447018SVictor Perevertkin }
982ba447018SVictor Perevertkin }
983ba447018SVictor Perevertkin
984ba447018SVictor Perevertkin /* If found copy */
985ba447018SVictor Perevertkin if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
986ba447018SVictor Perevertkin {
987ba447018SVictor Perevertkin DeviceLength = SymlinkInformation->Name.Length;
988ba447018SVictor Perevertkin DeviceString = AllocatePool(DeviceLength);
989ba447018SVictor Perevertkin if (!DeviceString)
990ba447018SVictor Perevertkin {
991ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
992ba447018SVictor Perevertkin }
993ba447018SVictor Perevertkin
994ba447018SVictor Perevertkin RtlCopyMemory(DeviceString, SymlinkInformation->Name.Buffer, DeviceLength);
995ba447018SVictor Perevertkin /* Ensure we are in the right namespace; [1] can be ? */
996ba447018SVictor Perevertkin DeviceString[1] = L'\\';
997ba447018SVictor Perevertkin }
998ba447018SVictor Perevertkin }
999ba447018SVictor Perevertkin
1000ba447018SVictor Perevertkin /* If we found something */
1001ba447018SVictor Perevertkin if (DeviceString)
1002ba447018SVictor Perevertkin {
1003ba447018SVictor Perevertkin /* At least, we will return our length */
1004ba447018SVictor Perevertkin ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSzLength = DeviceLength;
1005ba447018SVictor Perevertkin /* MOUNTMGR_VOLUME_PATHS is a string + a ULONG */
1006ba447018SVictor Perevertkin Irp->IoStatus.Information = DeviceLength + sizeof(ULONG);
1007ba447018SVictor Perevertkin
1008ba447018SVictor Perevertkin /* If we have enough room for copying the string */
1009ba447018SVictor Perevertkin if (sizeof(ULONG) + DeviceLength <= Stack->Parameters.DeviceIoControl.OutputBufferLength)
1010ba447018SVictor Perevertkin {
1011ba447018SVictor Perevertkin /* Copy it */
1012ba447018SVictor Perevertkin if (DeviceLength)
1013ba447018SVictor Perevertkin {
1014ba447018SVictor Perevertkin RtlCopyMemory(((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz, DeviceString, DeviceLength);
1015ba447018SVictor Perevertkin }
1016ba447018SVictor Perevertkin
1017ba447018SVictor Perevertkin /* And double zero at its end - this is needed in case of multiple paths which are separated by a single 0 */
1018ba447018SVictor Perevertkin FreePool(DeviceString);
1019ba447018SVictor Perevertkin ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR)] = 0;
1020ba447018SVictor Perevertkin ((PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer)->MultiSz[DeviceLength / sizeof(WCHAR) + 1] = 0;
1021ba447018SVictor Perevertkin
1022ba447018SVictor Perevertkin return STATUS_SUCCESS;
1023ba447018SVictor Perevertkin }
1024ba447018SVictor Perevertkin else
1025ba447018SVictor Perevertkin {
1026ba447018SVictor Perevertkin /* Just return appropriate size and leave */
1027ba447018SVictor Perevertkin FreePool(DeviceString);
1028ba447018SVictor Perevertkin Irp->IoStatus.Information = sizeof(ULONG);
1029ba447018SVictor Perevertkin return STATUS_BUFFER_OVERFLOW;
1030ba447018SVictor Perevertkin }
1031ba447018SVictor Perevertkin }
1032ba447018SVictor Perevertkin
1033ba447018SVictor Perevertkin /* Fail */
1034ba447018SVictor Perevertkin return STATUS_NOT_FOUND;
1035ba447018SVictor Perevertkin }
1036ba447018SVictor Perevertkin
1037ba447018SVictor Perevertkin /*
1038ba447018SVictor Perevertkin * @implemented
1039ba447018SVictor Perevertkin */
1040ba447018SVictor Perevertkin NTSTATUS
MountMgrValidateBackPointer(IN PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry,IN PDEVICE_INFORMATION DeviceInformation,OUT PBOOLEAN Invalid)1041ba447018SVictor Perevertkin MountMgrValidateBackPointer(IN PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry,
1042ba447018SVictor Perevertkin IN PDEVICE_INFORMATION DeviceInformation,
1043ba447018SVictor Perevertkin OUT PBOOLEAN Invalid)
1044ba447018SVictor Perevertkin {
1045ba447018SVictor Perevertkin HANDLE Handle;
1046ba447018SVictor Perevertkin NTSTATUS Status;
1047ba447018SVictor Perevertkin PLIST_ENTRY SymlinksEntry;
1048ba447018SVictor Perevertkin IO_STATUS_BLOCK IoStatusBlock;
1049ba447018SVictor Perevertkin PREPARSE_DATA_BUFFER ReparseData;
1050ba447018SVictor Perevertkin OBJECT_ATTRIBUTES ObjectAttributes;
1051ba447018SVictor Perevertkin UNICODE_STRING FullName, SubstituteName;
1052ba447018SVictor Perevertkin PSYMLINK_INFORMATION SymlinkInformation;
1053ba447018SVictor Perevertkin
1054ba447018SVictor Perevertkin /* Initialize & allocate a string big enough to contain our complete mount point name */
1055b8525ce7SVictor Perevertkin FullName.Length = 0;
1056b8525ce7SVictor Perevertkin FullName.MaximumLength = AssociatedDeviceEntry->String.Length
1057b8525ce7SVictor Perevertkin + AssociatedDeviceEntry->DeviceInformation->DeviceName.Length
1058b8525ce7SVictor Perevertkin + sizeof(WCHAR)
1059b8525ce7SVictor Perevertkin + sizeof(UNICODE_NULL);
1060ba447018SVictor Perevertkin FullName.Buffer = AllocatePool(FullName.MaximumLength);
1061ba447018SVictor Perevertkin if (!FullName.Buffer)
1062ba447018SVictor Perevertkin {
1063ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1064ba447018SVictor Perevertkin }
1065ba447018SVictor Perevertkin
1066ba447018SVictor Perevertkin /* Create the path */
1067b8525ce7SVictor Perevertkin RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->DeviceInformation->DeviceName);
1068b8525ce7SVictor Perevertkin FullName.Buffer[FullName.Length / sizeof(WCHAR)] = L'\\';
1069b8525ce7SVictor Perevertkin RtlAppendUnicodeStringToString(&FullName, &AssociatedDeviceEntry->String);
1070ba447018SVictor Perevertkin FullName.Buffer[FullName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1071ba447018SVictor Perevertkin
1072ba447018SVictor Perevertkin /* Open it to query the reparse point */
1073ba447018SVictor Perevertkin InitializeObjectAttributes(&ObjectAttributes,
1074ba447018SVictor Perevertkin &FullName,
1075ba447018SVictor Perevertkin OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1076ba447018SVictor Perevertkin NULL,
1077ba447018SVictor Perevertkin NULL);
1078ba447018SVictor Perevertkin Status = ZwOpenFile(&Handle,
1079ba447018SVictor Perevertkin SYNCHRONIZE | FILE_READ_ATTRIBUTES,
1080ba447018SVictor Perevertkin &ObjectAttributes, &IoStatusBlock,
1081ba447018SVictor Perevertkin FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1082ba447018SVictor Perevertkin FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT);
1083ba447018SVictor Perevertkin FreePool(FullName.Buffer);
1084ba447018SVictor Perevertkin
1085ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
1086ba447018SVictor Perevertkin {
1087ba447018SVictor Perevertkin *Invalid = TRUE;
1088ba447018SVictor Perevertkin return STATUS_SUCCESS;
1089ba447018SVictor Perevertkin }
1090ba447018SVictor Perevertkin
1091ba447018SVictor Perevertkin /* Allocate a buffer big enough to read reparse data */
1092ba447018SVictor Perevertkin ReparseData = AllocatePool(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1093ba447018SVictor Perevertkin if (ReparseData == NULL)
1094ba447018SVictor Perevertkin {
1095ba447018SVictor Perevertkin ZwClose(Handle);
1096ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1097ba447018SVictor Perevertkin }
1098ba447018SVictor Perevertkin
1099ba447018SVictor Perevertkin /* Query reparse data */
1100ba447018SVictor Perevertkin Status = ZwFsControlFile(Handle,
1101ba447018SVictor Perevertkin NULL, NULL, NULL,
1102ba447018SVictor Perevertkin &IoStatusBlock,
1103ba447018SVictor Perevertkin FSCTL_GET_REPARSE_POINT,
1104ba447018SVictor Perevertkin NULL, 0,
1105ba447018SVictor Perevertkin ReparseData, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1106ba447018SVictor Perevertkin ZwClose(Handle);
1107ba447018SVictor Perevertkin
1108ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
1109ba447018SVictor Perevertkin {
1110ba447018SVictor Perevertkin FreePool(ReparseData);
1111ba447018SVictor Perevertkin *Invalid = TRUE;
1112ba447018SVictor Perevertkin return STATUS_SUCCESS;
1113ba447018SVictor Perevertkin }
1114ba447018SVictor Perevertkin
1115ba447018SVictor Perevertkin /* Create a string with the substitute name */
1116ba447018SVictor Perevertkin SubstituteName.Length = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
1117ba447018SVictor Perevertkin SubstituteName.MaximumLength = SubstituteName.Length;
1118ba447018SVictor Perevertkin SubstituteName.Buffer = (PWSTR)((ULONG_PTR)ReparseData->SymbolicLinkReparseBuffer.PathBuffer + ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset);
1119ba447018SVictor Perevertkin
1120ba447018SVictor Perevertkin /* If that's a volume name that matches our associated device, that's a success! */
1121ba447018SVictor Perevertkin if (MOUNTMGR_IS_VOLUME_NAME(&SubstituteName))
1122ba447018SVictor Perevertkin {
1123ba447018SVictor Perevertkin if (SubstituteName.Length == 98 && SubstituteName.Buffer[1] == L'?')
1124ba447018SVictor Perevertkin {
1125ba447018SVictor Perevertkin for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
1126ba447018SVictor Perevertkin SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
1127ba447018SVictor Perevertkin SymlinksEntry = SymlinksEntry->Flink)
1128ba447018SVictor Perevertkin {
1129ba447018SVictor Perevertkin SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1130ba447018SVictor Perevertkin
1131ba447018SVictor Perevertkin if (RtlEqualUnicodeString(&SubstituteName, &SymlinkInformation->Name, TRUE))
1132ba447018SVictor Perevertkin {
1133ba447018SVictor Perevertkin FreePool(ReparseData);
1134ba447018SVictor Perevertkin return STATUS_SUCCESS;
1135ba447018SVictor Perevertkin }
1136ba447018SVictor Perevertkin }
1137ba447018SVictor Perevertkin }
1138ba447018SVictor Perevertkin }
1139ba447018SVictor Perevertkin
1140ba447018SVictor Perevertkin FreePool(ReparseData);
1141ba447018SVictor Perevertkin *Invalid = TRUE;
1142ba447018SVictor Perevertkin return STATUS_SUCCESS;
1143ba447018SVictor Perevertkin }
1144ba447018SVictor Perevertkin
1145ba447018SVictor Perevertkin /*
1146ba447018SVictor Perevertkin * @implemented
1147ba447018SVictor Perevertkin */
1148ba447018SVictor Perevertkin NTSTATUS
MountMgrQueryVolumePaths(IN PDEVICE_EXTENSION DeviceExtension,IN PDEVICE_INFORMATION DeviceInformation,IN PLIST_ENTRY DeviceInfoList,OUT PMOUNTMGR_VOLUME_PATHS * VolumePaths,OUT PDEVICE_INFORMATION * FailedDevice)1149ba447018SVictor Perevertkin MountMgrQueryVolumePaths(IN PDEVICE_EXTENSION DeviceExtension,
1150ba447018SVictor Perevertkin IN PDEVICE_INFORMATION DeviceInformation,
1151ba447018SVictor Perevertkin IN PLIST_ENTRY DeviceInfoList,
1152ba447018SVictor Perevertkin OUT PMOUNTMGR_VOLUME_PATHS * VolumePaths,
1153ba447018SVictor Perevertkin OUT PDEVICE_INFORMATION *FailedDevice)
1154ba447018SVictor Perevertkin {
1155ba447018SVictor Perevertkin ULONG Written;
1156ba447018SVictor Perevertkin NTSTATUS Status;
1157ba447018SVictor Perevertkin PLIST_ENTRY Entry;
1158ba447018SVictor Perevertkin PSYMLINK_INFORMATION SymlinkInformation;
1159ba447018SVictor Perevertkin PDEVICE_INFORMATION_ENTRY DeviceInfoEntry;
1160ba447018SVictor Perevertkin PASSOCIATED_DEVICE_ENTRY AssociatedDeviceEntry;
1161ba447018SVictor Perevertkin PMOUNTMGR_VOLUME_PATHS * Paths = NULL, * CurrentPath;
1162ba447018SVictor Perevertkin ULONG OutputPathLength, NumberOfPaths, ReturnedPaths;
1163ba447018SVictor Perevertkin
1164ba447018SVictor Perevertkin /* We return at least null char */
1165ba447018SVictor Perevertkin OutputPathLength = sizeof(UNICODE_NULL);
1166ba447018SVictor Perevertkin
1167ba447018SVictor Perevertkin for (Entry = DeviceInformation->SymbolicLinksListHead.Flink;
1168ba447018SVictor Perevertkin Entry != &(DeviceInformation->SymbolicLinksListHead);
1169ba447018SVictor Perevertkin Entry = Entry->Flink)
1170ba447018SVictor Perevertkin {
1171ba447018SVictor Perevertkin SymlinkInformation = CONTAINING_RECORD(Entry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
1172ba447018SVictor Perevertkin
1173ba447018SVictor Perevertkin /* Try to find the drive letter (ie, DOS device) */
1174ba447018SVictor Perevertkin if (MOUNTMGR_IS_DRIVE_LETTER(&SymlinkInformation->Name) && SymlinkInformation->Online)
1175ba447018SVictor Perevertkin {
1176ba447018SVictor Perevertkin /* We'll return the letter */
1177ba447018SVictor Perevertkin OutputPathLength = 4 * sizeof(WCHAR);
1178ba447018SVictor Perevertkin break;
1179ba447018SVictor Perevertkin }
1180ba447018SVictor Perevertkin }
1181ba447018SVictor Perevertkin
1182ba447018SVictor Perevertkin /* We didn't find any */
1183ba447018SVictor Perevertkin if (Entry == &(DeviceInformation->SymbolicLinksListHead))
1184ba447018SVictor Perevertkin {
1185ba447018SVictor Perevertkin SymlinkInformation = NULL;
1186ba447018SVictor Perevertkin }
1187ba447018SVictor Perevertkin
1188ba447018SVictor Perevertkin /* Do we have any device info to return? */
1189ba447018SVictor Perevertkin for (Entry = DeviceInfoList->Flink; Entry != DeviceInfoList; Entry = Entry->Flink)
1190ba447018SVictor Perevertkin {
1191ba447018SVictor Perevertkin DeviceInfoEntry = CONTAINING_RECORD(Entry, DEVICE_INFORMATION_ENTRY, DeviceInformationEntry);
1192ba447018SVictor Perevertkin
1193ba447018SVictor Perevertkin /* Matching current device */
1194ba447018SVictor Perevertkin if (DeviceInfoEntry->DeviceInformation == DeviceInformation)
1195ba447018SVictor Perevertkin {
1196ba447018SVictor Perevertkin /* Allocate the output buffer */
1197ba447018SVictor Perevertkin *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1198ba447018SVictor Perevertkin if (*VolumePaths == NULL)
1199ba447018SVictor Perevertkin {
1200ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1201ba447018SVictor Perevertkin }
1202ba447018SVictor Perevertkin
1203ba447018SVictor Perevertkin /* Set size */
1204ba447018SVictor Perevertkin (*VolumePaths)->MultiSzLength = OutputPathLength;
1205ba447018SVictor Perevertkin /* If we have a drive letter, return it */
1206ba447018SVictor Perevertkin if (SymlinkInformation != NULL)
1207ba447018SVictor Perevertkin {
1208ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1209ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[1] = L':';
1210ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1211ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[3] = UNICODE_NULL;
1212ba447018SVictor Perevertkin }
1213ba447018SVictor Perevertkin else
1214ba447018SVictor Perevertkin {
1215ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[0] = UNICODE_NULL;
1216ba447018SVictor Perevertkin }
1217ba447018SVictor Perevertkin
1218ba447018SVictor Perevertkin return STATUS_SUCCESS;
1219ba447018SVictor Perevertkin }
1220ba447018SVictor Perevertkin }
1221ba447018SVictor Perevertkin
1222ba447018SVictor Perevertkin /* Allocate a new device entry */
1223ba447018SVictor Perevertkin DeviceInfoEntry = AllocatePool(sizeof(DEVICE_INFORMATION_ENTRY));
1224ba447018SVictor Perevertkin if (DeviceInfoEntry == NULL)
1225ba447018SVictor Perevertkin {
1226ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1227ba447018SVictor Perevertkin }
1228ba447018SVictor Perevertkin
1229ba447018SVictor Perevertkin /* Add it to the list */
1230ba447018SVictor Perevertkin DeviceInfoEntry->DeviceInformation = DeviceInformation;
1231ba447018SVictor Perevertkin InsertTailList(DeviceInfoList, &DeviceInfoEntry->DeviceInformationEntry);
1232ba447018SVictor Perevertkin
1233ba447018SVictor Perevertkin NumberOfPaths = 0;
1234ba447018SVictor Perevertkin /* Count the amount of devices we will have to handle */
1235ba447018SVictor Perevertkin if (!IsListEmpty(&DeviceInformation->AssociatedDevicesHead))
1236ba447018SVictor Perevertkin {
1237ba447018SVictor Perevertkin for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1238ba447018SVictor Perevertkin Entry != &DeviceInformation->AssociatedDevicesHead;
1239ba447018SVictor Perevertkin Entry = Entry->Flink)
1240ba447018SVictor Perevertkin {
1241ba447018SVictor Perevertkin ++NumberOfPaths;
1242ba447018SVictor Perevertkin }
1243ba447018SVictor Perevertkin
1244ba447018SVictor Perevertkin ASSERT(NumberOfPaths != 0);
1245ba447018SVictor Perevertkin /* And allocate a big enough buffer */
1246ba447018SVictor Perevertkin Paths = AllocatePool(NumberOfPaths * sizeof(PMOUNTMGR_VOLUME_PATHS));
1247ba447018SVictor Perevertkin if (Paths == NULL)
1248ba447018SVictor Perevertkin {
1249ba447018SVictor Perevertkin RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1250ba447018SVictor Perevertkin FreePool(DeviceInfoEntry);
1251ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1252ba447018SVictor Perevertkin }
1253ba447018SVictor Perevertkin }
1254ba447018SVictor Perevertkin
1255ba447018SVictor Perevertkin /* Start the hot loop to gather all the paths and be able to compute total output length! */
1256ba447018SVictor Perevertkin ReturnedPaths = 0;
1257ba447018SVictor Perevertkin CurrentPath = Paths;
1258ba447018SVictor Perevertkin for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1259ba447018SVictor Perevertkin Entry != &DeviceInformation->AssociatedDevicesHead;
1260ba447018SVictor Perevertkin Entry = Entry->Flink)
1261ba447018SVictor Perevertkin {
1262ba447018SVictor Perevertkin USHORT InnerStrings;
1263ba447018SVictor Perevertkin BOOLEAN Invalid = FALSE;
1264ba447018SVictor Perevertkin
1265ba447018SVictor Perevertkin AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1266ba447018SVictor Perevertkin
1267ba447018SVictor Perevertkin /* Validate the fact its a mount point by query reparse data */
1268ba447018SVictor Perevertkin Status = MountMgrValidateBackPointer(AssociatedDeviceEntry, DeviceInformation, &Invalid);
1269ba447018SVictor Perevertkin
1270ba447018SVictor Perevertkin /* If we found an invalid device, that's a failure */
1271ba447018SVictor Perevertkin if (Invalid)
1272ba447018SVictor Perevertkin {
1273ba447018SVictor Perevertkin *FailedDevice = AssociatedDeviceEntry->DeviceInformation;
1274ba447018SVictor Perevertkin Status = STATUS_UNSUCCESSFUL;
1275ba447018SVictor Perevertkin }
1276ba447018SVictor Perevertkin
1277ba447018SVictor Perevertkin /* Check whether we failed, if so, bail out */
1278ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
1279ba447018SVictor Perevertkin {
1280ba447018SVictor Perevertkin ULONG i;
1281ba447018SVictor Perevertkin
1282ba447018SVictor Perevertkin for (i = 0; i < ReturnedPaths; ++i)
1283ba447018SVictor Perevertkin {
1284ba447018SVictor Perevertkin FreePool(Paths[i]);
1285ba447018SVictor Perevertkin }
1286ba447018SVictor Perevertkin
1287ba447018SVictor Perevertkin if (Paths != NULL)
1288ba447018SVictor Perevertkin {
1289ba447018SVictor Perevertkin FreePool(Paths);
1290ba447018SVictor Perevertkin }
1291ba447018SVictor Perevertkin RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1292ba447018SVictor Perevertkin FreePool(DeviceInfoEntry);
1293ba447018SVictor Perevertkin return Status;
1294ba447018SVictor Perevertkin }
1295ba447018SVictor Perevertkin
1296ba447018SVictor Perevertkin /* Query associated paths (hello ourselves :-)) */
1297ba447018SVictor Perevertkin Status = MountMgrQueryVolumePaths(DeviceExtension,
1298ba447018SVictor Perevertkin AssociatedDeviceEntry->DeviceInformation,
1299ba447018SVictor Perevertkin DeviceInfoList,
1300ba447018SVictor Perevertkin CurrentPath,
1301ba447018SVictor Perevertkin FailedDevice);
1302ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
1303ba447018SVictor Perevertkin {
1304ba447018SVictor Perevertkin ULONG i;
1305ba447018SVictor Perevertkin
1306ba447018SVictor Perevertkin for (i = 0; i < ReturnedPaths; ++i)
1307ba447018SVictor Perevertkin {
1308ba447018SVictor Perevertkin FreePool(Paths[i]);
1309ba447018SVictor Perevertkin }
1310ba447018SVictor Perevertkin
1311ba447018SVictor Perevertkin if (Paths != NULL)
1312ba447018SVictor Perevertkin {
1313ba447018SVictor Perevertkin FreePool(Paths);
1314ba447018SVictor Perevertkin }
1315ba447018SVictor Perevertkin RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1316ba447018SVictor Perevertkin FreePool(DeviceInfoEntry);
1317ba447018SVictor Perevertkin return Status;
1318ba447018SVictor Perevertkin }
1319ba447018SVictor Perevertkin
1320ba447018SVictor Perevertkin /* Count the number of strings we have in the multi string buffer */
1321ba447018SVictor Perevertkin InnerStrings = 0;
1322ba447018SVictor Perevertkin if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1323ba447018SVictor Perevertkin {
1324ba447018SVictor Perevertkin ULONG i;
1325ba447018SVictor Perevertkin PWSTR MultiSz = (*CurrentPath)->MultiSz;
1326ba447018SVictor Perevertkin
1327ba447018SVictor Perevertkin for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR); ++i, ++MultiSz)
1328ba447018SVictor Perevertkin {
1329ba447018SVictor Perevertkin if (*MultiSz == UNICODE_NULL)
1330ba447018SVictor Perevertkin {
1331ba447018SVictor Perevertkin ++InnerStrings;
1332ba447018SVictor Perevertkin }
1333ba447018SVictor Perevertkin }
1334ba447018SVictor Perevertkin }
1335ba447018SVictor Perevertkin
1336ba447018SVictor Perevertkin /* We returned one more path (ie, one more allocated buffer) */
1337ba447018SVictor Perevertkin ++ReturnedPaths;
1338ba447018SVictor Perevertkin /* Move the next pointer to use in the array */
1339ba447018SVictor Perevertkin ++CurrentPath;
1340ba447018SVictor Perevertkin /* Multiply String.Length by the number of found paths, we always add it after a path */
1341ba447018SVictor Perevertkin OutputPathLength += (*CurrentPath)->MultiSzLength + InnerStrings * AssociatedDeviceEntry->String.Length - sizeof(UNICODE_NULL);
1342ba447018SVictor Perevertkin }
1343ba447018SVictor Perevertkin
1344ba447018SVictor Perevertkin /* Allocate the output buffer */
1345ba447018SVictor Perevertkin *VolumePaths = AllocatePool(sizeof(ULONG) + OutputPathLength);
1346ba447018SVictor Perevertkin if (*VolumePaths == NULL)
1347ba447018SVictor Perevertkin {
1348ba447018SVictor Perevertkin ULONG i;
1349ba447018SVictor Perevertkin
1350ba447018SVictor Perevertkin for (i = 0; i < ReturnedPaths; ++i)
1351ba447018SVictor Perevertkin {
1352ba447018SVictor Perevertkin FreePool(Paths[i]);
1353ba447018SVictor Perevertkin }
1354ba447018SVictor Perevertkin
1355ba447018SVictor Perevertkin if (Paths != NULL)
1356ba447018SVictor Perevertkin {
1357ba447018SVictor Perevertkin FreePool(Paths);
1358ba447018SVictor Perevertkin }
1359ba447018SVictor Perevertkin RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1360ba447018SVictor Perevertkin FreePool(DeviceInfoEntry);
1361ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1362ba447018SVictor Perevertkin }
1363ba447018SVictor Perevertkin
1364ba447018SVictor Perevertkin Written = 0;
1365ba447018SVictor Perevertkin /* If we had found a DOS letter, that's the first thing we return */
1366ba447018SVictor Perevertkin (*VolumePaths)->MultiSzLength = OutputPathLength;
1367ba447018SVictor Perevertkin if (SymlinkInformation != NULL)
1368ba447018SVictor Perevertkin {
1369ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[0] = SymlinkInformation->Name.Buffer[LETTER_POSITION];
1370ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[1] = L':';
1371ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[2] = UNICODE_NULL;
1372ba447018SVictor Perevertkin Written = 3;
1373ba447018SVictor Perevertkin }
1374ba447018SVictor Perevertkin
1375ba447018SVictor Perevertkin /* Now, browse again all our paths to return them */
1376ba447018SVictor Perevertkin CurrentPath = Paths;
1377ba447018SVictor Perevertkin for (Entry = DeviceInformation->AssociatedDevicesHead.Flink;
1378ba447018SVictor Perevertkin Entry != &DeviceInformation->AssociatedDevicesHead;
1379ba447018SVictor Perevertkin Entry = Entry->Flink)
1380ba447018SVictor Perevertkin {
1381ba447018SVictor Perevertkin AssociatedDeviceEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
1382ba447018SVictor Perevertkin
1383ba447018SVictor Perevertkin /* If we had a path... */
1384ba447018SVictor Perevertkin if ((*CurrentPath)->MultiSzLength != sizeof(UNICODE_NULL))
1385ba447018SVictor Perevertkin {
1386ba447018SVictor Perevertkin ULONG i, Offset;
1387ba447018SVictor Perevertkin PWSTR MultiSz;
1388ba447018SVictor Perevertkin
1389ba447018SVictor Perevertkin /* This offset is used to "jump" into MultiSz, so, start with the string begin (ie, skip MultiSzLength) */
1390ba447018SVictor Perevertkin Offset = sizeof(ULONG);
1391ba447018SVictor Perevertkin /* Browse every single letter, and skip last UNICODE_NULL */
1392ba447018SVictor Perevertkin for (i = 0; i < (*CurrentPath)->MultiSzLength / sizeof(WCHAR) - 1; ++i)
1393ba447018SVictor Perevertkin {
1394ba447018SVictor Perevertkin /* Get the letter */
1395ba447018SVictor Perevertkin MultiSz = (PWSTR)((ULONG_PTR)(*CurrentPath) + Offset);
1396ba447018SVictor Perevertkin /* If it was part of the path, just return it */
1397ba447018SVictor Perevertkin if (*MultiSz != UNICODE_NULL)
1398ba447018SVictor Perevertkin {
1399ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[Written] = *MultiSz;
1400ba447018SVictor Perevertkin }
1401ba447018SVictor Perevertkin else
1402ba447018SVictor Perevertkin {
1403ba447018SVictor Perevertkin /* Otherwise, as planed, return our whole associated device name */
1404ba447018SVictor Perevertkin RtlCopyMemory(&(*VolumePaths)->MultiSz[Written],
1405ba447018SVictor Perevertkin AssociatedDeviceEntry->String.Buffer,
1406ba447018SVictor Perevertkin AssociatedDeviceEntry->String.Length);
1407ba447018SVictor Perevertkin Written += AssociatedDeviceEntry->String.Length / sizeof(WCHAR);
1408ba447018SVictor Perevertkin /* And don't forget to nullify */
1409ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1410ba447018SVictor Perevertkin }
1411ba447018SVictor Perevertkin
1412ba447018SVictor Perevertkin /* We at least return a letter or a null char */
1413ba447018SVictor Perevertkin ++Written;
1414ba447018SVictor Perevertkin /* Move to the next letter */
1415ba447018SVictor Perevertkin Offset += sizeof(WCHAR);
1416ba447018SVictor Perevertkin }
1417ba447018SVictor Perevertkin }
1418ba447018SVictor Perevertkin
1419ba447018SVictor Perevertkin FreePool(*CurrentPath);
1420ba447018SVictor Perevertkin ++CurrentPath;
1421ba447018SVictor Perevertkin }
1422ba447018SVictor Perevertkin
1423ba447018SVictor Perevertkin /* MultiSz: don't forget last null char */
1424ba447018SVictor Perevertkin (*VolumePaths)->MultiSz[Written] = UNICODE_NULL;
1425ba447018SVictor Perevertkin /* Cleanup everything and return success! */
1426ba447018SVictor Perevertkin if (Paths != NULL)
1427ba447018SVictor Perevertkin {
1428ba447018SVictor Perevertkin FreePool(Paths);
1429ba447018SVictor Perevertkin }
1430ba447018SVictor Perevertkin RemoveEntryList(&DeviceInfoEntry->DeviceInformationEntry);
1431ba447018SVictor Perevertkin FreePool(DeviceInfoEntry);
1432ba447018SVictor Perevertkin return STATUS_SUCCESS;
1433ba447018SVictor Perevertkin }
1434ba447018SVictor Perevertkin
1435ba447018SVictor Perevertkin /*
1436ba447018SVictor Perevertkin * @implemented
1437ba447018SVictor Perevertkin */
1438ba447018SVictor Perevertkin NTSTATUS
MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)1439ba447018SVictor Perevertkin MountMgrQueryDosVolumePaths(IN PDEVICE_EXTENSION DeviceExtension,
1440ba447018SVictor Perevertkin IN PIRP Irp)
1441ba447018SVictor Perevertkin {
1442ba447018SVictor Perevertkin NTSTATUS Status;
1443ba447018SVictor Perevertkin PLIST_ENTRY Entry;
1444ba447018SVictor Perevertkin LIST_ENTRY Devices;
1445ba447018SVictor Perevertkin BOOLEAN NeedNotification;
1446ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
1447ba447018SVictor Perevertkin UNICODE_STRING SymbolicName;
1448ba447018SVictor Perevertkin ULONG Attempts, OutputLength;
1449ba447018SVictor Perevertkin PMOUNTMGR_TARGET_NAME Target;
1450ba447018SVictor Perevertkin PMOUNTMGR_VOLUME_PATHS Paths, Output;
1451ba447018SVictor Perevertkin RECONCILE_WORK_ITEM_CONTEXT ReconcileContext;
1452ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation, ListDeviceInfo, FailedDevice;
1453ba447018SVictor Perevertkin
1454ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
1455ba447018SVictor Perevertkin
1456ba447018SVictor Perevertkin /* Validate input size */
1457ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1458ba447018SVictor Perevertkin {
1459ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1460ba447018SVictor Perevertkin }
1461ba447018SVictor Perevertkin
1462ba447018SVictor Perevertkin /* Ensure we have received UNICODE_STRING */
1463ba447018SVictor Perevertkin Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1464ba447018SVictor Perevertkin if (Target->DeviceNameLength & 1)
1465ba447018SVictor Perevertkin {
1466ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1467ba447018SVictor Perevertkin }
1468ba447018SVictor Perevertkin
1469ba447018SVictor Perevertkin /* Validate the entry structure size */
1470ba447018SVictor Perevertkin if (Target->DeviceNameLength + FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1471ba447018SVictor Perevertkin {
1472ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1473ba447018SVictor Perevertkin }
1474ba447018SVictor Perevertkin
1475ba447018SVictor Perevertkin /* Ensure we can at least return needed size */
1476ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
1477ba447018SVictor Perevertkin {
1478ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1479ba447018SVictor Perevertkin }
1480ba447018SVictor Perevertkin
1481ba447018SVictor Perevertkin /* Construct string for query */
1482ba447018SVictor Perevertkin SymbolicName.Length = Target->DeviceNameLength;
1483ba447018SVictor Perevertkin SymbolicName.MaximumLength = Target->DeviceNameLength + sizeof(UNICODE_NULL);
1484ba447018SVictor Perevertkin SymbolicName.Buffer = Target->DeviceName;
1485ba447018SVictor Perevertkin
1486ba447018SVictor Perevertkin /* Find device with our info */
1487ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1488ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
1489ba447018SVictor Perevertkin {
1490ba447018SVictor Perevertkin return Status;
1491ba447018SVictor Perevertkin }
1492ba447018SVictor Perevertkin
1493ba447018SVictor Perevertkin NeedNotification = FALSE;
1494ba447018SVictor Perevertkin Attempts = 0;
1495ba447018SVictor Perevertkin for (;;)
1496ba447018SVictor Perevertkin {
1497ba447018SVictor Perevertkin FailedDevice = NULL;
1498ba447018SVictor Perevertkin InitializeListHead(&Devices);
1499ba447018SVictor Perevertkin
1500ba447018SVictor Perevertkin /* Query paths */
1501ba447018SVictor Perevertkin Status = MountMgrQueryVolumePaths(DeviceExtension, DeviceInformation, &Devices, &Paths, &FailedDevice);
1502ba447018SVictor Perevertkin if (NT_SUCCESS(Status))
1503ba447018SVictor Perevertkin {
1504ba447018SVictor Perevertkin break;
1505ba447018SVictor Perevertkin }
1506ba447018SVictor Perevertkin
1507ba447018SVictor Perevertkin /* If it failed for generic reason (memory, whatever), bail out (ie, FailedDevice not set) */
1508ba447018SVictor Perevertkin if (FailedDevice == NULL)
1509ba447018SVictor Perevertkin {
1510ba447018SVictor Perevertkin return Status;
1511ba447018SVictor Perevertkin }
1512ba447018SVictor Perevertkin
1513ba447018SVictor Perevertkin /* If PnP, let's notify in case of success */
1514ba447018SVictor Perevertkin if (!DeviceInformation->ManuallyRegistered)
1515ba447018SVictor Perevertkin {
1516ba447018SVictor Perevertkin NeedNotification = TRUE;
1517ba447018SVictor Perevertkin }
1518ba447018SVictor Perevertkin
1519ba447018SVictor Perevertkin /* Reconcile database */
1520ba447018SVictor Perevertkin ReconcileContext.DeviceExtension = DeviceExtension;
1521ba447018SVictor Perevertkin ReconcileContext.DeviceInformation = FailedDevice;
1522ba447018SVictor Perevertkin KeReleaseSemaphore(&DeviceExtension->DeviceLock, IO_NO_INCREMENT, 1, FALSE);
1523ba447018SVictor Perevertkin ReconcileThisDatabaseWithMasterWorker(&ReconcileContext);
1524ba447018SVictor Perevertkin KeWaitForSingleObject(&DeviceExtension->DeviceLock, Executive, KernelMode, FALSE, NULL);
1525ba447018SVictor Perevertkin
1526ba447018SVictor Perevertkin /* Look for our device, to check it's online */
1527ba447018SVictor Perevertkin for (Entry = DeviceExtension->DeviceListHead.Flink;
1528ba447018SVictor Perevertkin Entry != &DeviceExtension->DeviceListHead;
1529ba447018SVictor Perevertkin Entry = Entry->Flink)
1530ba447018SVictor Perevertkin {
1531ba447018SVictor Perevertkin ListDeviceInfo = CONTAINING_RECORD(Entry, DEVICE_INFORMATION, DeviceListEntry);
1532ba447018SVictor Perevertkin /* It's online, it's OK! */
1533ba447018SVictor Perevertkin if (ListDeviceInfo == DeviceInformation)
1534ba447018SVictor Perevertkin {
1535ba447018SVictor Perevertkin break;
1536ba447018SVictor Perevertkin }
1537ba447018SVictor Perevertkin }
1538ba447018SVictor Perevertkin
1539ba447018SVictor Perevertkin /* It's not online, it's not good */
1540ba447018SVictor Perevertkin if (Entry == &DeviceExtension->DeviceListHead)
1541ba447018SVictor Perevertkin {
1542ba447018SVictor Perevertkin return STATUS_OBJECT_NAME_NOT_FOUND;
1543ba447018SVictor Perevertkin }
1544ba447018SVictor Perevertkin
1545ba447018SVictor Perevertkin /* Increase attempts count */
1546ba447018SVictor Perevertkin ++Attempts;
1547ba447018SVictor Perevertkin /* Don't look forever and fail if we get out of attempts */
1548ba447018SVictor Perevertkin if (Attempts >= 1000)
1549ba447018SVictor Perevertkin {
1550ba447018SVictor Perevertkin return Status;
1551ba447018SVictor Perevertkin }
1552ba447018SVictor Perevertkin }
1553ba447018SVictor Perevertkin
1554ba447018SVictor Perevertkin /* We need to notify? Go ahead */
1555ba447018SVictor Perevertkin if (NeedNotification)
1556ba447018SVictor Perevertkin {
1557ba447018SVictor Perevertkin MountMgrNotifyNameChange(DeviceExtension, &SymbolicName, FALSE);
1558ba447018SVictor Perevertkin }
1559ba447018SVictor Perevertkin
1560ba447018SVictor Perevertkin /* Get output buffer */
1561ba447018SVictor Perevertkin Output = (PMOUNTMGR_VOLUME_PATHS)Irp->AssociatedIrp.SystemBuffer;
1562ba447018SVictor Perevertkin
1563ba447018SVictor Perevertkin /* Set required size */
1564ba447018SVictor Perevertkin Output->MultiSzLength = Paths->MultiSzLength;
1565ba447018SVictor Perevertkin
1566ba447018SVictor Perevertkin /* Compute total length */
1567ba447018SVictor Perevertkin OutputLength = Output->MultiSzLength + sizeof(ULONG);
1568ba447018SVictor Perevertkin
1569ba447018SVictor Perevertkin /* If it cannot fit, just return need size and quit */
1570ba447018SVictor Perevertkin if (OutputLength > Stack->Parameters.DeviceIoControl.OutputBufferLength)
1571ba447018SVictor Perevertkin {
1572ba447018SVictor Perevertkin Irp->IoStatus.Information = sizeof(ULONG);
1573ba447018SVictor Perevertkin FreePool(Paths);
1574ba447018SVictor Perevertkin return STATUS_BUFFER_OVERFLOW;
1575ba447018SVictor Perevertkin }
1576ba447018SVictor Perevertkin
1577ba447018SVictor Perevertkin /* Copy data and quit */
1578ba447018SVictor Perevertkin Irp->IoStatus.Information = OutputLength;
1579ba447018SVictor Perevertkin RtlCopyMemory(Output->MultiSz, Paths->MultiSz, Output->MultiSzLength);
1580ba447018SVictor Perevertkin FreePool(Paths);
1581ba447018SVictor Perevertkin return STATUS_SUCCESS;
1582ba447018SVictor Perevertkin }
1583ba447018SVictor Perevertkin
1584ba447018SVictor Perevertkin /*
1585ba447018SVictor Perevertkin * @implemented
1586ba447018SVictor Perevertkin */
1587ba447018SVictor Perevertkin NTSTATUS
MountMgrKeepLinksWhenOffline(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)1588ba447018SVictor Perevertkin MountMgrKeepLinksWhenOffline(IN PDEVICE_EXTENSION DeviceExtension,
1589ba447018SVictor Perevertkin IN PIRP Irp)
1590ba447018SVictor Perevertkin {
1591ba447018SVictor Perevertkin NTSTATUS Status;
1592ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
1593ba447018SVictor Perevertkin UNICODE_STRING SymbolicName;
1594ba447018SVictor Perevertkin PMOUNTMGR_TARGET_NAME Target;
1595ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation;
1596ba447018SVictor Perevertkin
1597ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
1598ba447018SVictor Perevertkin
1599ba447018SVictor Perevertkin /* Validate input */
1600ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1601ba447018SVictor Perevertkin {
1602ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1603ba447018SVictor Perevertkin }
1604ba447018SVictor Perevertkin
1605ba447018SVictor Perevertkin Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1606ba447018SVictor Perevertkin if (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1607ba447018SVictor Perevertkin {
1608ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1609ba447018SVictor Perevertkin }
1610ba447018SVictor Perevertkin
1611ba447018SVictor Perevertkin SymbolicName.Length =
1612ba447018SVictor Perevertkin SymbolicName.MaximumLength = Target->DeviceNameLength;
1613ba447018SVictor Perevertkin SymbolicName.Buffer = Target->DeviceName;
1614ba447018SVictor Perevertkin
1615ba447018SVictor Perevertkin /* Find the associated device */
1616ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, &SymbolicName, FALSE, &DeviceInformation);
1617ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
1618ba447018SVictor Perevertkin {
1619ba447018SVictor Perevertkin return Status;
1620ba447018SVictor Perevertkin }
1621ba447018SVictor Perevertkin
1622ba447018SVictor Perevertkin /* Mark we want to keep links */
1623ba447018SVictor Perevertkin DeviceInformation->KeepLinks = TRUE;
1624ba447018SVictor Perevertkin
1625ba447018SVictor Perevertkin return STATUS_SUCCESS;
1626ba447018SVictor Perevertkin }
1627ba447018SVictor Perevertkin
1628ba447018SVictor Perevertkin /*
1629ba447018SVictor Perevertkin * @implemented
1630ba447018SVictor Perevertkin */
1631ba447018SVictor Perevertkin NTSTATUS
MountMgrVolumeArrivalNotification(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)1632ba447018SVictor Perevertkin MountMgrVolumeArrivalNotification(IN PDEVICE_EXTENSION DeviceExtension,
1633ba447018SVictor Perevertkin IN PIRP Irp)
1634ba447018SVictor Perevertkin {
1635ba447018SVictor Perevertkin NTSTATUS Status;
1636ba447018SVictor Perevertkin BOOLEAN OldState;
1637ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
1638ba447018SVictor Perevertkin UNICODE_STRING SymbolicName;
1639ba447018SVictor Perevertkin PMOUNTMGR_TARGET_NAME Target;
1640ba447018SVictor Perevertkin
1641ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
1642ba447018SVictor Perevertkin
1643ba447018SVictor Perevertkin /* Validate input */
1644ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_TARGET_NAME))
1645ba447018SVictor Perevertkin {
1646ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1647ba447018SVictor Perevertkin }
1648ba447018SVictor Perevertkin
1649ba447018SVictor Perevertkin Target = (PMOUNTMGR_TARGET_NAME)Irp->AssociatedIrp.SystemBuffer;
1650ba447018SVictor Perevertkin if (Target->DeviceNameLength + sizeof(USHORT) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1651ba447018SVictor Perevertkin {
1652ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1653ba447018SVictor Perevertkin }
1654ba447018SVictor Perevertkin
1655ba447018SVictor Perevertkin SymbolicName.Length =
1656ba447018SVictor Perevertkin SymbolicName.MaximumLength = Target->DeviceNameLength;
1657ba447018SVictor Perevertkin SymbolicName.Buffer = Target->DeviceName;
1658ba447018SVictor Perevertkin
1659ba447018SVictor Perevertkin /* Disable hard errors */
1660ba447018SVictor Perevertkin OldState = PsGetThreadHardErrorsAreDisabled(PsGetCurrentThread());
1661ba447018SVictor Perevertkin PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), TRUE);
1662ba447018SVictor Perevertkin
1663ba447018SVictor Perevertkin /* Call real worker */
1664ba447018SVictor Perevertkin Status = MountMgrMountedDeviceArrival(DeviceExtension, &SymbolicName, TRUE);
1665ba447018SVictor Perevertkin
1666ba447018SVictor Perevertkin PsSetThreadHardErrorsAreDisabled(PsGetCurrentThread(), OldState);
1667ba447018SVictor Perevertkin
1668ba447018SVictor Perevertkin return Status;
1669ba447018SVictor Perevertkin }
1670ba447018SVictor Perevertkin
1671ba447018SVictor Perevertkin /*
1672ba447018SVictor Perevertkin * @implemented
1673ba447018SVictor Perevertkin */
1674ba447018SVictor Perevertkin NTSTATUS
MountMgrQueryPoints(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)1675ba447018SVictor Perevertkin MountMgrQueryPoints(IN PDEVICE_EXTENSION DeviceExtension,
1676ba447018SVictor Perevertkin IN PIRP Irp)
1677ba447018SVictor Perevertkin {
1678ba447018SVictor Perevertkin NTSTATUS Status;
1679ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
1680ba447018SVictor Perevertkin PMOUNTDEV_UNIQUE_ID UniqueId;
1681ba447018SVictor Perevertkin PMOUNTMGR_MOUNT_POINT MountPoint;
1682ba447018SVictor Perevertkin UNICODE_STRING SymbolicName, DeviceName;
1683ba447018SVictor Perevertkin
1684ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
1685ba447018SVictor Perevertkin
1686ba447018SVictor Perevertkin /* Validate input... */
1687ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1688ba447018SVictor Perevertkin {
1689ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1690ba447018SVictor Perevertkin }
1691ba447018SVictor Perevertkin
1692ba447018SVictor Perevertkin MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1693ba447018SVictor Perevertkin if (!MountPoint->SymbolicLinkNameLength)
1694ba447018SVictor Perevertkin {
1695ba447018SVictor Perevertkin MountPoint->SymbolicLinkNameOffset = 0;
1696ba447018SVictor Perevertkin }
1697ba447018SVictor Perevertkin
1698ba447018SVictor Perevertkin if (!MountPoint->UniqueIdLength)
1699ba447018SVictor Perevertkin {
1700ba447018SVictor Perevertkin MountPoint->UniqueIdOffset = 0;
1701ba447018SVictor Perevertkin }
1702ba447018SVictor Perevertkin
1703ba447018SVictor Perevertkin if (!MountPoint->DeviceNameLength)
1704ba447018SVictor Perevertkin {
1705ba447018SVictor Perevertkin MountPoint->DeviceNameOffset = 0;
1706ba447018SVictor Perevertkin }
1707ba447018SVictor Perevertkin
1708ba447018SVictor Perevertkin /* Addresses can't be odd */
1709ba447018SVictor Perevertkin if ((MountPoint->SymbolicLinkNameOffset & 1) ||
1710ba447018SVictor Perevertkin (MountPoint->SymbolicLinkNameLength & 1))
1711ba447018SVictor Perevertkin {
1712ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1713ba447018SVictor Perevertkin }
1714ba447018SVictor Perevertkin
1715ba447018SVictor Perevertkin if ((MountPoint->UniqueIdOffset & 1) ||
1716ba447018SVictor Perevertkin (MountPoint->UniqueIdLength & 1))
1717ba447018SVictor Perevertkin {
1718ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1719ba447018SVictor Perevertkin }
1720ba447018SVictor Perevertkin
1721ba447018SVictor Perevertkin if ((MountPoint->DeviceNameOffset & 1) ||
1722ba447018SVictor Perevertkin (MountPoint->DeviceNameLength & 1))
1723ba447018SVictor Perevertkin {
1724ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1725ba447018SVictor Perevertkin }
1726ba447018SVictor Perevertkin
1727ba447018SVictor Perevertkin /* We can't go beyond */
1728ba447018SVictor Perevertkin if (((ULONG)MountPoint->SymbolicLinkNameLength + MountPoint->UniqueIdLength +
1729ba447018SVictor Perevertkin MountPoint->DeviceNameLength) > Stack->Parameters.DeviceIoControl.InputBufferLength)
1730ba447018SVictor Perevertkin {
1731ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1732ba447018SVictor Perevertkin }
1733ba447018SVictor Perevertkin
1734ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTMGR_MOUNT_POINTS))
1735ba447018SVictor Perevertkin {
1736ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1737ba447018SVictor Perevertkin }
1738ba447018SVictor Perevertkin
1739ba447018SVictor Perevertkin /* If caller provided a Symlink, use it */
1740ba447018SVictor Perevertkin if (MountPoint->SymbolicLinkNameLength != 0)
1741ba447018SVictor Perevertkin {
1742ba447018SVictor Perevertkin if (MountPoint->SymbolicLinkNameLength > MAXSHORT)
1743ba447018SVictor Perevertkin {
1744ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1745ba447018SVictor Perevertkin }
1746ba447018SVictor Perevertkin
1747ba447018SVictor Perevertkin SymbolicName.Length = MountPoint->SymbolicLinkNameLength;
1748ba447018SVictor Perevertkin SymbolicName.MaximumLength = MountPoint->SymbolicLinkNameLength + sizeof(WCHAR);
1749ba447018SVictor Perevertkin SymbolicName.Buffer = AllocatePool(SymbolicName.MaximumLength);
1750ba447018SVictor Perevertkin if (!SymbolicName.Buffer)
1751ba447018SVictor Perevertkin {
1752ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1753ba447018SVictor Perevertkin }
1754ba447018SVictor Perevertkin
1755ba447018SVictor Perevertkin RtlCopyMemory(SymbolicName.Buffer,
1756ba447018SVictor Perevertkin (PWSTR)((ULONG_PTR)MountPoint + MountPoint->SymbolicLinkNameOffset),
1757ba447018SVictor Perevertkin SymbolicName.Length);
1758ba447018SVictor Perevertkin SymbolicName.Buffer[SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1759ba447018SVictor Perevertkin
1760ba447018SVictor Perevertkin /* Query links using it */
1761ba447018SVictor Perevertkin Status = QueryPointsFromSymbolicLinkName(DeviceExtension, &SymbolicName, Irp);
1762ba447018SVictor Perevertkin FreePool(SymbolicName.Buffer);
1763ba447018SVictor Perevertkin }
1764ba447018SVictor Perevertkin /* If user provided an unique ID */
1765ba447018SVictor Perevertkin else if (MountPoint->UniqueIdLength != 0)
1766ba447018SVictor Perevertkin {
1767ba447018SVictor Perevertkin UniqueId = AllocatePool(MountPoint->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1768ba447018SVictor Perevertkin if (!UniqueId)
1769ba447018SVictor Perevertkin {
1770ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1771ba447018SVictor Perevertkin }
1772ba447018SVictor Perevertkin
1773ba447018SVictor Perevertkin UniqueId->UniqueIdLength = MountPoint->UniqueIdLength;
1774ba447018SVictor Perevertkin RtlCopyMemory(UniqueId->UniqueId,
1775ba447018SVictor Perevertkin (PVOID)((ULONG_PTR)MountPoint + MountPoint->UniqueIdOffset),
1776ba447018SVictor Perevertkin MountPoint->UniqueIdLength);
1777ba447018SVictor Perevertkin
1778ba447018SVictor Perevertkin /* Query links using it */
1779ba447018SVictor Perevertkin Status = QueryPointsFromMemory(DeviceExtension, Irp, UniqueId, NULL);
1780ba447018SVictor Perevertkin FreePool(UniqueId);
1781ba447018SVictor Perevertkin }
1782ba447018SVictor Perevertkin /* If caller provided a device name */
1783ba447018SVictor Perevertkin else if (MountPoint->DeviceNameLength != 0)
1784ba447018SVictor Perevertkin {
1785ba447018SVictor Perevertkin if (MountPoint->DeviceNameLength > MAXSHORT)
1786ba447018SVictor Perevertkin {
1787ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1788ba447018SVictor Perevertkin }
1789ba447018SVictor Perevertkin
1790ba447018SVictor Perevertkin DeviceName.Length = MountPoint->DeviceNameLength;
1791ba447018SVictor Perevertkin DeviceName.MaximumLength = MountPoint->DeviceNameLength + sizeof(WCHAR);
1792ba447018SVictor Perevertkin DeviceName.Buffer = AllocatePool(DeviceName.MaximumLength);
1793ba447018SVictor Perevertkin if (!DeviceName.Buffer)
1794ba447018SVictor Perevertkin {
1795ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1796ba447018SVictor Perevertkin }
1797ba447018SVictor Perevertkin
1798ba447018SVictor Perevertkin RtlCopyMemory(DeviceName.Buffer,
1799ba447018SVictor Perevertkin (PWSTR)((ULONG_PTR)MountPoint + MountPoint->DeviceNameOffset),
1800ba447018SVictor Perevertkin DeviceName.Length);
1801ba447018SVictor Perevertkin DeviceName.Buffer[DeviceName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1802ba447018SVictor Perevertkin
1803ba447018SVictor Perevertkin /* Query links using it */
1804ba447018SVictor Perevertkin Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, &DeviceName);
1805ba447018SVictor Perevertkin FreePool(DeviceName.Buffer);
1806ba447018SVictor Perevertkin }
1807ba447018SVictor Perevertkin else
1808ba447018SVictor Perevertkin {
1809ba447018SVictor Perevertkin /* Otherwise, query all links */
1810ba447018SVictor Perevertkin Status = QueryPointsFromMemory(DeviceExtension, Irp, NULL, NULL);
1811ba447018SVictor Perevertkin }
1812ba447018SVictor Perevertkin
1813ba447018SVictor Perevertkin return Status;
1814ba447018SVictor Perevertkin }
1815ba447018SVictor Perevertkin
1816ba447018SVictor Perevertkin /*
1817ba447018SVictor Perevertkin * @implemented
1818ba447018SVictor Perevertkin */
1819ba447018SVictor Perevertkin NTSTATUS
MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)1820ba447018SVictor Perevertkin MountMgrDeletePoints(IN PDEVICE_EXTENSION DeviceExtension,
1821ba447018SVictor Perevertkin IN PIRP Irp)
1822ba447018SVictor Perevertkin {
1823ba447018SVictor Perevertkin ULONG Link;
1824ba447018SVictor Perevertkin NTSTATUS Status;
1825ba447018SVictor Perevertkin BOOLEAN CreateNoDrive;
1826ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
1827ba447018SVictor Perevertkin PMOUNTDEV_UNIQUE_ID UniqueId;
1828ba447018SVictor Perevertkin PMOUNTMGR_MOUNT_POINT MountPoint;
1829ba447018SVictor Perevertkin PMOUNTMGR_MOUNT_POINTS MountPoints;
1830ba447018SVictor Perevertkin UNICODE_STRING SymbolicName, DeviceName;
1831ba447018SVictor Perevertkin
1832ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
1833ba447018SVictor Perevertkin
1834ba447018SVictor Perevertkin /* Validate input */
1835ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_MOUNT_POINT))
1836ba447018SVictor Perevertkin {
1837ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
1838ba447018SVictor Perevertkin }
1839ba447018SVictor Perevertkin
1840ba447018SVictor Perevertkin /* Query points */
1841ba447018SVictor Perevertkin MountPoint = (PMOUNTMGR_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
1842ba447018SVictor Perevertkin CreateNoDrive = (MountPoint->SymbolicLinkNameOffset && MountPoint->SymbolicLinkNameLength);
1843ba447018SVictor Perevertkin
1844ba447018SVictor Perevertkin Status = MountMgrQueryPoints(DeviceExtension, Irp);
1845ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
1846ba447018SVictor Perevertkin {
1847ba447018SVictor Perevertkin return Status;
1848ba447018SVictor Perevertkin }
1849ba447018SVictor Perevertkin
1850ba447018SVictor Perevertkin /* For all the points matching the request */
1851ba447018SVictor Perevertkin MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1852ba447018SVictor Perevertkin for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1853ba447018SVictor Perevertkin {
1854ba447018SVictor Perevertkin SymbolicName.Length = MountPoints->MountPoints[Link].SymbolicLinkNameLength;
1855ba447018SVictor Perevertkin SymbolicName.MaximumLength = SymbolicName.Length + sizeof(WCHAR);
1856ba447018SVictor Perevertkin SymbolicName.Buffer = AllocatePool(SymbolicName.MaximumLength);
1857ba447018SVictor Perevertkin if (!SymbolicName.Buffer)
1858ba447018SVictor Perevertkin {
1859ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1860ba447018SVictor Perevertkin }
1861ba447018SVictor Perevertkin
1862ba447018SVictor Perevertkin RtlCopyMemory(SymbolicName.Buffer,
1863ba447018SVictor Perevertkin (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1864ba447018SVictor Perevertkin SymbolicName.Length);
1865ba447018SVictor Perevertkin SymbolicName.Buffer[SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1866ba447018SVictor Perevertkin
1867ba447018SVictor Perevertkin /* Create a no drive entry for the drive letters */
1868ba447018SVictor Perevertkin if (CreateNoDrive && IsDriveLetter(&SymbolicName))
1869ba447018SVictor Perevertkin {
1870ba447018SVictor Perevertkin UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1871ba447018SVictor Perevertkin if (UniqueId)
1872ba447018SVictor Perevertkin {
1873ba447018SVictor Perevertkin UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1874ba447018SVictor Perevertkin RtlCopyMemory(UniqueId->UniqueId,
1875ba447018SVictor Perevertkin (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1876ba447018SVictor Perevertkin MountPoints->MountPoints[Link].UniqueIdLength);
1877ba447018SVictor Perevertkin
1878ba447018SVictor Perevertkin CreateNoDriveLetterEntry(UniqueId);
1879ba447018SVictor Perevertkin FreePool(UniqueId);
1880ba447018SVictor Perevertkin }
1881ba447018SVictor Perevertkin }
1882ba447018SVictor Perevertkin
1883ba447018SVictor Perevertkin /* If there are no link any more, and no need to create a no drive entry */
1884ba447018SVictor Perevertkin if (Link == 0 && !CreateNoDrive)
1885ba447018SVictor Perevertkin {
1886ba447018SVictor Perevertkin /* Then, delete everything */
1887ba447018SVictor Perevertkin UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength);
1888ba447018SVictor Perevertkin if (UniqueId)
1889ba447018SVictor Perevertkin {
1890ba447018SVictor Perevertkin RtlCopyMemory(UniqueId,
1891ba447018SVictor Perevertkin (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1892ba447018SVictor Perevertkin MountPoints->MountPoints[Link].UniqueIdLength);
1893ba447018SVictor Perevertkin
1894ba447018SVictor Perevertkin DeleteNoDriveLetterEntry(UniqueId);
1895ba447018SVictor Perevertkin FreePool(UniqueId);
1896ba447018SVictor Perevertkin }
1897ba447018SVictor Perevertkin }
1898ba447018SVictor Perevertkin
1899ba447018SVictor Perevertkin /* Delete all the information about the mount point */
1900ba447018SVictor Perevertkin GlobalDeleteSymbolicLink(&SymbolicName);
1901ba447018SVictor Perevertkin DeleteSymbolicLinkNameFromMemory(DeviceExtension, &SymbolicName, FALSE);
1902ba447018SVictor Perevertkin RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE, DatabasePath, SymbolicName.Buffer);
1903ba447018SVictor Perevertkin FreePool(SymbolicName.Buffer);
1904ba447018SVictor Perevertkin
1905ba447018SVictor Perevertkin /* Notify the change */
1906ba447018SVictor Perevertkin DeviceName.Length = DeviceName.MaximumLength =
1907ba447018SVictor Perevertkin MountPoints->MountPoints[Link].DeviceNameLength;
1908ba447018SVictor Perevertkin DeviceName.Buffer = (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].DeviceNameOffset);
1909ba447018SVictor Perevertkin MountMgrNotifyNameChange(DeviceExtension, &DeviceName, TRUE);
1910ba447018SVictor Perevertkin }
1911ba447018SVictor Perevertkin
1912ba447018SVictor Perevertkin MountMgrNotify(DeviceExtension);
1913ba447018SVictor Perevertkin
1914ba447018SVictor Perevertkin return Status;
1915ba447018SVictor Perevertkin }
1916ba447018SVictor Perevertkin
1917ba447018SVictor Perevertkin /*
1918ba447018SVictor Perevertkin * @implemented
1919ba447018SVictor Perevertkin */
1920ba447018SVictor Perevertkin NTSTATUS
MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp)1921ba447018SVictor Perevertkin MountMgrDeletePointsDbOnly(IN PDEVICE_EXTENSION DeviceExtension,
1922ba447018SVictor Perevertkin IN PIRP Irp)
1923ba447018SVictor Perevertkin {
1924ba447018SVictor Perevertkin ULONG Link;
1925ba447018SVictor Perevertkin NTSTATUS Status;
1926ba447018SVictor Perevertkin UNICODE_STRING SymbolicName;
1927ba447018SVictor Perevertkin PMOUNTDEV_UNIQUE_ID UniqueId;
1928ba447018SVictor Perevertkin PMOUNTMGR_MOUNT_POINTS MountPoints;
1929ba447018SVictor Perevertkin
1930ba447018SVictor Perevertkin /* Query points */
1931ba447018SVictor Perevertkin Status = MountMgrQueryPoints(DeviceExtension, Irp);
1932ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
1933ba447018SVictor Perevertkin {
1934ba447018SVictor Perevertkin return Status;
1935ba447018SVictor Perevertkin }
1936ba447018SVictor Perevertkin
1937ba447018SVictor Perevertkin MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
1938ba447018SVictor Perevertkin if (MountPoints->NumberOfMountPoints == 0)
1939ba447018SVictor Perevertkin {
1940ba447018SVictor Perevertkin return Status;
1941ba447018SVictor Perevertkin }
1942ba447018SVictor Perevertkin
1943ba447018SVictor Perevertkin /* For all the mount points */
1944ba447018SVictor Perevertkin for (Link = 0; Link < MountPoints->NumberOfMountPoints; Link++)
1945ba447018SVictor Perevertkin {
1946ba447018SVictor Perevertkin SymbolicName.Length = MountPoints->MountPoints[Link].SymbolicLinkNameLength;
1947ba447018SVictor Perevertkin SymbolicName.MaximumLength = SymbolicName.Length + sizeof(WCHAR);
1948ba447018SVictor Perevertkin SymbolicName.Buffer = AllocatePool(SymbolicName.MaximumLength);
1949ba447018SVictor Perevertkin if (!SymbolicName.Buffer)
1950ba447018SVictor Perevertkin {
1951ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1952ba447018SVictor Perevertkin }
1953ba447018SVictor Perevertkin
1954ba447018SVictor Perevertkin RtlCopyMemory(SymbolicName.Buffer,
1955ba447018SVictor Perevertkin (PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].SymbolicLinkNameOffset),
1956ba447018SVictor Perevertkin SymbolicName.Length);
1957ba447018SVictor Perevertkin SymbolicName.Buffer[SymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1958ba447018SVictor Perevertkin
1959ba447018SVictor Perevertkin /* If the only mount point is a drive letter, then create a no letter drive entry */
1960ba447018SVictor Perevertkin if (MountPoints->NumberOfMountPoints == 1 && IsDriveLetter(&SymbolicName))
1961ba447018SVictor Perevertkin {
1962ba447018SVictor Perevertkin UniqueId = AllocatePool(MountPoints->MountPoints[Link].UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
1963ba447018SVictor Perevertkin if (UniqueId)
1964ba447018SVictor Perevertkin {
1965ba447018SVictor Perevertkin UniqueId->UniqueIdLength = MountPoints->MountPoints[Link].UniqueIdLength;
1966ba447018SVictor Perevertkin RtlCopyMemory(UniqueId->UniqueId,
1967ba447018SVictor Perevertkin (PMOUNTDEV_UNIQUE_ID)((ULONG_PTR)MountPoints + MountPoints->MountPoints[Link].UniqueIdOffset),
1968ba447018SVictor Perevertkin MountPoints->MountPoints[Link].UniqueIdLength);
1969ba447018SVictor Perevertkin
1970ba447018SVictor Perevertkin CreateNoDriveLetterEntry(UniqueId);
1971ba447018SVictor Perevertkin FreePool(UniqueId);
1972ba447018SVictor Perevertkin }
1973ba447018SVictor Perevertkin }
1974ba447018SVictor Perevertkin
1975ba447018SVictor Perevertkin /* Simply delete mount point from DB */
1976ba447018SVictor Perevertkin DeleteSymbolicLinkNameFromMemory(DeviceExtension, &SymbolicName, TRUE);
1977ba447018SVictor Perevertkin RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE, DatabasePath, SymbolicName.Buffer);
1978ba447018SVictor Perevertkin FreePool(SymbolicName.Buffer);
1979ba447018SVictor Perevertkin }
1980ba447018SVictor Perevertkin
1981ba447018SVictor Perevertkin return Status;
1982ba447018SVictor Perevertkin }
1983ba447018SVictor Perevertkin
1984ba447018SVictor Perevertkin /*
1985ba447018SVictor Perevertkin * @implemented
1986ba447018SVictor Perevertkin */
1987ba447018SVictor Perevertkin NTSTATUS
MountMgrVolumeMountPointChanged(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp,IN NTSTATUS LockStatus,OUT PUNICODE_STRING SourceDeviceName,OUT PUNICODE_STRING SourceSymbolicName,OUT PUNICODE_STRING TargetVolumeName)1988ba447018SVictor Perevertkin MountMgrVolumeMountPointChanged(IN PDEVICE_EXTENSION DeviceExtension,
1989ba447018SVictor Perevertkin IN PIRP Irp,
1990ba447018SVictor Perevertkin IN NTSTATUS LockStatus,
1991ba447018SVictor Perevertkin OUT PUNICODE_STRING SourceDeviceName,
1992ba447018SVictor Perevertkin OUT PUNICODE_STRING SourceSymbolicName,
1993ba447018SVictor Perevertkin OUT PUNICODE_STRING TargetVolumeName)
1994ba447018SVictor Perevertkin {
1995ba447018SVictor Perevertkin HANDLE Handle;
1996ba447018SVictor Perevertkin NTSTATUS Status;
1997ba447018SVictor Perevertkin PFILE_OBJECT FileObject;
1998ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
1999ba447018SVictor Perevertkin ULONG Length, SavedLength;
2000ba447018SVictor Perevertkin BOOLEAN FOReferenced = FALSE;
2001ba447018SVictor Perevertkin IO_STATUS_BLOCK IoStatusBlock;
2002ba447018SVictor Perevertkin OBJECT_ATTRIBUTES ObjectAttributes;
2003ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation;
2004ba447018SVictor Perevertkin OBJECT_NAME_INFORMATION ObjectNameInfo;
2005ba447018SVictor Perevertkin FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
2006ba447018SVictor Perevertkin PFILE_NAME_INFORMATION FileNameInfo = NULL;
2007ba447018SVictor Perevertkin PMOUNTMGR_VOLUME_MOUNT_POINT VolumeMountPoint;
2008ba447018SVictor Perevertkin POBJECT_NAME_INFORMATION ObjectNameInfoPtr = NULL;
2009ba447018SVictor Perevertkin UNICODE_STRING SourceVolumeName, TargetDeviceName;
2010ba447018SVictor Perevertkin
2011ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
2012ba447018SVictor Perevertkin
2013ba447018SVictor Perevertkin /* Validate input */
2014ba447018SVictor Perevertkin if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(MOUNTMGR_VOLUME_MOUNT_POINT))
2015ba447018SVictor Perevertkin {
2016ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
2017ba447018SVictor Perevertkin }
2018ba447018SVictor Perevertkin
2019ba447018SVictor Perevertkin VolumeMountPoint = (PMOUNTMGR_VOLUME_MOUNT_POINT)Irp->AssociatedIrp.SystemBuffer;
2020ba447018SVictor Perevertkin
2021ba447018SVictor Perevertkin if (((ULONG)VolumeMountPoint->SourceVolumeNameLength + VolumeMountPoint->TargetVolumeNameLength) <
2022ba447018SVictor Perevertkin Stack->Parameters.DeviceIoControl.InputBufferLength)
2023ba447018SVictor Perevertkin {
2024ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
2025ba447018SVictor Perevertkin }
2026ba447018SVictor Perevertkin
2027ba447018SVictor Perevertkin /* Get source volume name */
2028ba447018SVictor Perevertkin SourceVolumeName.Length =
2029ba447018SVictor Perevertkin SourceVolumeName.MaximumLength = VolumeMountPoint->SourceVolumeNameLength;
2030ba447018SVictor Perevertkin SourceVolumeName.Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset);
2031ba447018SVictor Perevertkin
2032ba447018SVictor Perevertkin InitializeObjectAttributes(&ObjectAttributes,
2033ba447018SVictor Perevertkin &SourceVolumeName,
2034ba447018SVictor Perevertkin OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
2035ba447018SVictor Perevertkin NULL,
2036ba447018SVictor Perevertkin NULL);
2037ba447018SVictor Perevertkin
2038ba447018SVictor Perevertkin /* Open it */
2039ba447018SVictor Perevertkin Status = ZwOpenFile(&Handle,
2040ba447018SVictor Perevertkin SYNCHRONIZE | FILE_READ_ATTRIBUTES,
2041ba447018SVictor Perevertkin &ObjectAttributes,
2042ba447018SVictor Perevertkin &IoStatusBlock,
2043ba447018SVictor Perevertkin FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2044ba447018SVictor Perevertkin FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT);
2045ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2046ba447018SVictor Perevertkin {
2047ba447018SVictor Perevertkin return Status;
2048ba447018SVictor Perevertkin }
2049ba447018SVictor Perevertkin
2050ba447018SVictor Perevertkin TargetDeviceName.Buffer = NULL;
2051ba447018SVictor Perevertkin
2052ba447018SVictor Perevertkin /* Query its attributes */
2053ba447018SVictor Perevertkin Status = ZwQueryVolumeInformationFile(Handle,
2054ba447018SVictor Perevertkin &IoStatusBlock,
2055ba447018SVictor Perevertkin &FsDeviceInfo,
2056ba447018SVictor Perevertkin sizeof(FsDeviceInfo),
2057ba447018SVictor Perevertkin FileFsDeviceInformation);
2058ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2059ba447018SVictor Perevertkin {
2060ba447018SVictor Perevertkin goto Cleanup;
2061ba447018SVictor Perevertkin }
2062ba447018SVictor Perevertkin
2063ba447018SVictor Perevertkin if (FsDeviceInfo.DeviceType != FILE_DEVICE_DISK && FsDeviceInfo.DeviceType != FILE_DEVICE_VIRTUAL_DISK)
2064ba447018SVictor Perevertkin {
2065ba447018SVictor Perevertkin goto Cleanup;
2066ba447018SVictor Perevertkin }
2067ba447018SVictor Perevertkin
2068ba447018SVictor Perevertkin if (FsDeviceInfo.Characteristics != (FILE_REMOTE_DEVICE | FILE_REMOVABLE_MEDIA))
2069ba447018SVictor Perevertkin {
2070ba447018SVictor Perevertkin goto Cleanup;
2071ba447018SVictor Perevertkin }
2072ba447018SVictor Perevertkin
2073ba447018SVictor Perevertkin /* Reference it */
2074ba447018SVictor Perevertkin Status = ObReferenceObjectByHandle(Handle, 0, *IoFileObjectType, KernelMode, (PVOID *)&FileObject, NULL);
2075ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2076ba447018SVictor Perevertkin {
2077ba447018SVictor Perevertkin goto Cleanup;
2078ba447018SVictor Perevertkin }
2079ba447018SVictor Perevertkin FOReferenced = TRUE;
2080ba447018SVictor Perevertkin
2081ba447018SVictor Perevertkin /* Get file name */
2082ba447018SVictor Perevertkin FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION));
2083ba447018SVictor Perevertkin if (!FileNameInfo)
2084ba447018SVictor Perevertkin {
2085ba447018SVictor Perevertkin Status = STATUS_INSUFFICIENT_RESOURCES;
2086ba447018SVictor Perevertkin goto Cleanup;
2087ba447018SVictor Perevertkin }
2088ba447018SVictor Perevertkin
2089ba447018SVictor Perevertkin Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2090ba447018SVictor Perevertkin sizeof(FILE_NAME_INFORMATION),
2091ba447018SVictor Perevertkin FileNameInformation);
2092ba447018SVictor Perevertkin if (Status == STATUS_BUFFER_OVERFLOW)
2093ba447018SVictor Perevertkin {
2094ba447018SVictor Perevertkin /* Now we have real length, use it */
2095ba447018SVictor Perevertkin Length = FileNameInfo->FileNameLength;
2096ba447018SVictor Perevertkin FreePool(FileNameInfo);
2097ba447018SVictor Perevertkin
2098ba447018SVictor Perevertkin FileNameInfo = AllocatePool(sizeof(FILE_NAME_INFORMATION) + Length);
2099ba447018SVictor Perevertkin if (!FileNameInfo)
2100ba447018SVictor Perevertkin {
2101ba447018SVictor Perevertkin Status = STATUS_INSUFFICIENT_RESOURCES;
2102ba447018SVictor Perevertkin goto Cleanup;
2103ba447018SVictor Perevertkin }
2104ba447018SVictor Perevertkin
2105ba447018SVictor Perevertkin /* Really query file name */
2106ba447018SVictor Perevertkin Status = ZwQueryInformationFile(Handle, &IoStatusBlock, FileNameInfo,
2107ba447018SVictor Perevertkin sizeof(FILE_NAME_INFORMATION) + Length,
2108ba447018SVictor Perevertkin FileNameInformation);
2109ba447018SVictor Perevertkin }
2110ba447018SVictor Perevertkin
2111ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2112ba447018SVictor Perevertkin {
2113ba447018SVictor Perevertkin goto Cleanup;
2114ba447018SVictor Perevertkin }
2115ba447018SVictor Perevertkin
2116ba447018SVictor Perevertkin /* Get symbolic name */
2117ba447018SVictor Perevertkin ObjectNameInfoPtr = &ObjectNameInfo;
2118ba447018SVictor Perevertkin SavedLength = sizeof(OBJECT_NAME_INFORMATION);
2119ba447018SVictor Perevertkin Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, sizeof(OBJECT_NAME_INFORMATION), &Length);
2120ba447018SVictor Perevertkin if (Status == STATUS_INFO_LENGTH_MISMATCH)
2121ba447018SVictor Perevertkin {
2122ba447018SVictor Perevertkin /* Once again, with proper size, it works better */
2123ba447018SVictor Perevertkin ObjectNameInfoPtr = AllocatePool(Length);
2124ba447018SVictor Perevertkin if (!ObjectNameInfoPtr)
2125ba447018SVictor Perevertkin {
2126ba447018SVictor Perevertkin Status = STATUS_INSUFFICIENT_RESOURCES;
2127ba447018SVictor Perevertkin goto Cleanup;
2128ba447018SVictor Perevertkin }
2129ba447018SVictor Perevertkin
2130ba447018SVictor Perevertkin SavedLength = Length;
2131ba447018SVictor Perevertkin Status = ObQueryNameString(FileObject->DeviceObject, ObjectNameInfoPtr, SavedLength, &Length);
2132ba447018SVictor Perevertkin }
2133ba447018SVictor Perevertkin
2134ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2135ba447018SVictor Perevertkin {
2136ba447018SVictor Perevertkin goto Cleanup;
2137ba447018SVictor Perevertkin }
2138ba447018SVictor Perevertkin
2139ba447018SVictor Perevertkin /* Now, query the device name */
2140ba447018SVictor Perevertkin Status = QueryDeviceInformation(&ObjectNameInfoPtr->Name, SourceDeviceName,
2141ba447018SVictor Perevertkin NULL, NULL, NULL, NULL, NULL, NULL);
2142ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2143ba447018SVictor Perevertkin {
2144ba447018SVictor Perevertkin goto Cleanup;
2145ba447018SVictor Perevertkin }
2146ba447018SVictor Perevertkin
2147ba447018SVictor Perevertkin /* For target volume name, use input */
2148ba447018SVictor Perevertkin TargetVolumeName->Length =
2149ba447018SVictor Perevertkin TargetVolumeName->MaximumLength = VolumeMountPoint->TargetVolumeNameLength;
2150ba447018SVictor Perevertkin TargetVolumeName->Buffer = (PWSTR)((ULONG_PTR)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset);
2151ba447018SVictor Perevertkin
2152ba447018SVictor Perevertkin /* Query its device name */
2153ba447018SVictor Perevertkin Status = QueryDeviceInformation(TargetVolumeName, &TargetDeviceName,
2154ba447018SVictor Perevertkin NULL, NULL, NULL, NULL, NULL, NULL);
2155ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2156ba447018SVictor Perevertkin {
2157ba447018SVictor Perevertkin goto Cleanup;
2158ba447018SVictor Perevertkin }
2159ba447018SVictor Perevertkin
2160ba447018SVictor Perevertkin /* Return symbolic name */
2161ba447018SVictor Perevertkin SourceSymbolicName->Length =
2162ba447018SVictor Perevertkin SourceSymbolicName->MaximumLength = (USHORT)FileNameInfo->FileNameLength;
2163ba447018SVictor Perevertkin SourceSymbolicName->Buffer = (PWSTR)FileNameInfo;
2164ba447018SVictor Perevertkin /* memmove allows memory overlap */
2165ba447018SVictor Perevertkin RtlMoveMemory(SourceSymbolicName->Buffer, FileNameInfo->FileName, SourceSymbolicName->Length);
2166ba447018SVictor Perevertkin FileNameInfo = NULL;
2167ba447018SVictor Perevertkin
2168ba447018SVictor Perevertkin /* Notify the change */
2169ba447018SVictor Perevertkin MountMgrNotify(DeviceExtension);
2170ba447018SVictor Perevertkin MountMgrNotifyNameChange(DeviceExtension, &TargetDeviceName, TRUE);
2171ba447018SVictor Perevertkin
2172ba447018SVictor Perevertkin /* If we are locked, sync databases if possible */
2173ba447018SVictor Perevertkin if (NT_SUCCESS(LockStatus))
2174ba447018SVictor Perevertkin {
2175ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, SourceDeviceName, FALSE, &DeviceInformation);
2176ba447018SVictor Perevertkin if (NT_SUCCESS(Status))
2177ba447018SVictor Perevertkin {
2178ba447018SVictor Perevertkin ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
2179ba447018SVictor Perevertkin }
2180ba447018SVictor Perevertkin else
2181ba447018SVictor Perevertkin {
2182ba447018SVictor Perevertkin Status = STATUS_PENDING;
2183ba447018SVictor Perevertkin }
2184ba447018SVictor Perevertkin }
2185ba447018SVictor Perevertkin
2186ba447018SVictor Perevertkin Cleanup:
2187ba447018SVictor Perevertkin if (TargetDeviceName.Buffer)
2188ba447018SVictor Perevertkin {
2189ba447018SVictor Perevertkin FreePool(TargetDeviceName.Buffer);
2190ba447018SVictor Perevertkin }
2191ba447018SVictor Perevertkin
2192ba447018SVictor Perevertkin if (ObjectNameInfoPtr && ObjectNameInfoPtr != &ObjectNameInfo)
2193ba447018SVictor Perevertkin {
2194ba447018SVictor Perevertkin FreePool(ObjectNameInfoPtr);
2195ba447018SVictor Perevertkin }
2196ba447018SVictor Perevertkin
2197ba447018SVictor Perevertkin if (FileNameInfo)
2198ba447018SVictor Perevertkin {
2199ba447018SVictor Perevertkin FreePool(FileNameInfo);
2200ba447018SVictor Perevertkin }
2201ba447018SVictor Perevertkin
2202ba447018SVictor Perevertkin if (FOReferenced)
2203ba447018SVictor Perevertkin {
2204ba447018SVictor Perevertkin ObDereferenceObject(FileObject);
2205ba447018SVictor Perevertkin }
2206ba447018SVictor Perevertkin
2207ba447018SVictor Perevertkin return Status;
2208ba447018SVictor Perevertkin }
2209ba447018SVictor Perevertkin
2210ba447018SVictor Perevertkin /*
2211ba447018SVictor Perevertkin * @implemented
2212ba447018SVictor Perevertkin */
2213ba447018SVictor Perevertkin NTSTATUS
MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp,IN NTSTATUS LockStatus)2214ba447018SVictor Perevertkin MountMgrVolumeMountPointCreated(IN PDEVICE_EXTENSION DeviceExtension,
2215ba447018SVictor Perevertkin IN PIRP Irp,
2216ba447018SVictor Perevertkin IN NTSTATUS LockStatus)
2217ba447018SVictor Perevertkin {
2218ba447018SVictor Perevertkin LONG Offset;
2219ba447018SVictor Perevertkin BOOLEAN Found;
2220ba447018SVictor Perevertkin NTSTATUS Status;
2221ba447018SVictor Perevertkin HANDLE RemoteDatabase;
2222ba447018SVictor Perevertkin PMOUNTDEV_UNIQUE_ID UniqueId;
2223ba447018SVictor Perevertkin PDATABASE_ENTRY DatabaseEntry;
2224ba447018SVictor Perevertkin PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2225ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2226ba447018SVictor Perevertkin UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2227ba447018SVictor Perevertkin
2228ba447018SVictor Perevertkin /* Initialize string */
2229ba447018SVictor Perevertkin LinkTarget.Length = 0;
2230ba447018SVictor Perevertkin LinkTarget.MaximumLength = 0xC8;
2231ba447018SVictor Perevertkin LinkTarget.Buffer = AllocatePool(LinkTarget.MaximumLength);
2232ba447018SVictor Perevertkin if (LinkTarget.Buffer == NULL)
2233ba447018SVictor Perevertkin {
2234ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
2235ba447018SVictor Perevertkin }
2236ba447018SVictor Perevertkin
2237ba447018SVictor Perevertkin /* If the mount point was created, then, it changed!
2238ba447018SVictor Perevertkin * Also use it to query some information
2239ba447018SVictor Perevertkin */
2240ba447018SVictor Perevertkin Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2241ba447018SVictor Perevertkin /* Pending means DB are under synchronization, bail out */
2242ba447018SVictor Perevertkin if (Status == STATUS_PENDING)
2243ba447018SVictor Perevertkin {
2244ba447018SVictor Perevertkin FreePool(LinkTarget.Buffer);
2245ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2246ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2247ba447018SVictor Perevertkin return STATUS_SUCCESS;
2248ba447018SVictor Perevertkin }
2249ba447018SVictor Perevertkin else if (!NT_SUCCESS(Status))
2250ba447018SVictor Perevertkin {
2251ba447018SVictor Perevertkin FreePool(LinkTarget.Buffer);
2252ba447018SVictor Perevertkin return Status;
2253ba447018SVictor Perevertkin }
2254ba447018SVictor Perevertkin
2255ba447018SVictor Perevertkin /* Query the device information */
2256ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2257ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2258ba447018SVictor Perevertkin {
2259ba447018SVictor Perevertkin /* If it failed, first try to get volume name */
2260ba447018SVictor Perevertkin Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2261ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2262ba447018SVictor Perevertkin {
2263ba447018SVictor Perevertkin /* Then, try to read the symlink */
2264ba447018SVictor Perevertkin Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2265ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2266ba447018SVictor Perevertkin {
2267ba447018SVictor Perevertkin FreePool(LinkTarget.Buffer);
2268ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2269ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2270ba447018SVictor Perevertkin return Status;
2271ba447018SVictor Perevertkin }
2272ba447018SVictor Perevertkin }
2273ba447018SVictor Perevertkin else
2274ba447018SVictor Perevertkin {
2275ba447018SVictor Perevertkin FreePool(VolumeName.Buffer);
2276ba447018SVictor Perevertkin }
2277ba447018SVictor Perevertkin
2278ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2279ba447018SVictor Perevertkin
2280ba447018SVictor Perevertkin SourceDeviceName.Length = LinkTarget.Length;
2281ba447018SVictor Perevertkin SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2282ba447018SVictor Perevertkin SourceDeviceName.Buffer = LinkTarget.Buffer;
2283ba447018SVictor Perevertkin
2284ba447018SVictor Perevertkin /* Now that we have the correct source, reattempt to query information */
2285ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2286ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2287ba447018SVictor Perevertkin {
2288ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2289ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2290ba447018SVictor Perevertkin return Status;
2291ba447018SVictor Perevertkin }
2292ba447018SVictor Perevertkin }
2293ba447018SVictor Perevertkin
2294ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2295ba447018SVictor Perevertkin
2296ba447018SVictor Perevertkin /* Get information about target device */
2297ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2298ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2299ba447018SVictor Perevertkin {
2300ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2301ba447018SVictor Perevertkin return Status;
2302ba447018SVictor Perevertkin }
2303ba447018SVictor Perevertkin
2304ba447018SVictor Perevertkin /* Notify if not disabled */
2305ba447018SVictor Perevertkin if (!TargetDeviceInformation->SkipNotifications)
2306ba447018SVictor Perevertkin {
2307ba447018SVictor Perevertkin PostOnlineNotification(DeviceExtension, &TargetDeviceInformation->SymbolicName);
2308ba447018SVictor Perevertkin }
2309ba447018SVictor Perevertkin
2310ba447018SVictor Perevertkin /* Open the remote database */
2311ba447018SVictor Perevertkin RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2312ba447018SVictor Perevertkin if (RemoteDatabase == 0)
2313ba447018SVictor Perevertkin {
2314ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2315ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
2316ba447018SVictor Perevertkin }
2317ba447018SVictor Perevertkin
2318ba447018SVictor Perevertkin /* Browse all the entries */
2319ba447018SVictor Perevertkin Offset = 0;
2320ba447018SVictor Perevertkin Found = FALSE;
2321ba447018SVictor Perevertkin for (;;)
2322ba447018SVictor Perevertkin {
2323ba447018SVictor Perevertkin DatabaseEntry = GetRemoteDatabaseEntry(RemoteDatabase, Offset);
2324ba447018SVictor Perevertkin if (DatabaseEntry == NULL)
2325ba447018SVictor Perevertkin {
2326ba447018SVictor Perevertkin break;
2327ba447018SVictor Perevertkin }
2328ba447018SVictor Perevertkin
2329ba447018SVictor Perevertkin /* Try to find ourselves */
2330ba447018SVictor Perevertkin DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2331ba447018SVictor Perevertkin DbName.Length = DbName.MaximumLength;
2332ba447018SVictor Perevertkin DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2333ba447018SVictor Perevertkin if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2334ba447018SVictor Perevertkin {
2335ba447018SVictor Perevertkin /* Reference ourselves and update the entry */
2336ba447018SVictor Perevertkin ++DatabaseEntry->EntryReferences;
2337ba447018SVictor Perevertkin Status = WriteRemoteDatabaseEntry(RemoteDatabase, Offset, DatabaseEntry);
2338ba447018SVictor Perevertkin FreePool(DatabaseEntry);
2339ba447018SVictor Perevertkin Found = TRUE;
2340ba447018SVictor Perevertkin break;
2341ba447018SVictor Perevertkin }
2342ba447018SVictor Perevertkin
2343ba447018SVictor Perevertkin Offset += DatabaseEntry->EntrySize;
2344ba447018SVictor Perevertkin FreePool(DatabaseEntry);
2345ba447018SVictor Perevertkin }
2346ba447018SVictor Perevertkin
2347ba447018SVictor Perevertkin /* We couldn't find ourselves, we'll have to add ourselves */
2348ba447018SVictor Perevertkin if (!Found)
2349ba447018SVictor Perevertkin {
2350ba447018SVictor Perevertkin ULONG EntrySize;
2351ba447018SVictor Perevertkin PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2352ba447018SVictor Perevertkin
2353ba447018SVictor Perevertkin /* Query the device unique ID */
2354ba447018SVictor Perevertkin Status = QueryDeviceInformation(&TargetVolumeName, NULL, &UniqueId, NULL, NULL, NULL, NULL, NULL);
2355ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2356ba447018SVictor Perevertkin {
2357ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2358ba447018SVictor Perevertkin CloseRemoteDatabase(RemoteDatabase);
2359ba447018SVictor Perevertkin return Status;
2360ba447018SVictor Perevertkin }
2361ba447018SVictor Perevertkin
2362ba447018SVictor Perevertkin /* Allocate a database entry */
2363ba447018SVictor Perevertkin EntrySize = UniqueId->UniqueIdLength + TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2364ba447018SVictor Perevertkin DatabaseEntry = AllocatePool(EntrySize);
2365ba447018SVictor Perevertkin if (DatabaseEntry == NULL)
2366ba447018SVictor Perevertkin {
2367ba447018SVictor Perevertkin FreePool(UniqueId);
2368ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2369ba447018SVictor Perevertkin CloseRemoteDatabase(RemoteDatabase);
2370ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
2371ba447018SVictor Perevertkin }
2372ba447018SVictor Perevertkin
2373ba447018SVictor Perevertkin /* Fill it in */
2374ba447018SVictor Perevertkin DatabaseEntry->EntrySize = EntrySize;
2375ba447018SVictor Perevertkin DatabaseEntry->EntryReferences = 1;
2376ba447018SVictor Perevertkin DatabaseEntry->SymbolicNameOffset = sizeof(DATABASE_ENTRY);
2377ba447018SVictor Perevertkin DatabaseEntry->SymbolicNameLength = TargetVolumeName.Length;
2378ba447018SVictor Perevertkin DatabaseEntry->UniqueIdOffset = TargetVolumeName.Length + sizeof(DATABASE_ENTRY);
2379ba447018SVictor Perevertkin DatabaseEntry->UniqueIdLength = UniqueId->UniqueIdLength;
2380ba447018SVictor Perevertkin RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + sizeof(DATABASE_ENTRY)), TargetVolumeName.Buffer, DatabaseEntry->SymbolicNameLength);
2381ba447018SVictor Perevertkin RtlCopyMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset), UniqueId->UniqueId, UniqueId->UniqueIdLength);
2382ba447018SVictor Perevertkin
2383ba447018SVictor Perevertkin /* And write it down */
2384ba447018SVictor Perevertkin Status = AddRemoteDatabaseEntry(RemoteDatabase, DatabaseEntry);
2385ba447018SVictor Perevertkin FreePool(DatabaseEntry);
2386ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2387ba447018SVictor Perevertkin {
2388ba447018SVictor Perevertkin FreePool(UniqueId);
2389ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2390ba447018SVictor Perevertkin CloseRemoteDatabase(RemoteDatabase);
2391ba447018SVictor Perevertkin return Status;
2392ba447018SVictor Perevertkin }
2393ba447018SVictor Perevertkin
2394ba447018SVictor Perevertkin /* And now, allocate an Unique ID item */
2395ba447018SVictor Perevertkin UniqueIdReplicate = AllocatePool(sizeof(UNIQUE_ID_REPLICATE));
2396ba447018SVictor Perevertkin if (UniqueIdReplicate == NULL)
2397ba447018SVictor Perevertkin {
2398ba447018SVictor Perevertkin FreePool(UniqueId);
2399ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2400ba447018SVictor Perevertkin CloseRemoteDatabase(RemoteDatabase);
2401ba447018SVictor Perevertkin return Status;
2402ba447018SVictor Perevertkin }
2403ba447018SVictor Perevertkin
2404ba447018SVictor Perevertkin /* To associate it with the device */
2405ba447018SVictor Perevertkin UniqueIdReplicate->UniqueId = UniqueId;
2406ba447018SVictor Perevertkin InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2407ba447018SVictor Perevertkin }
2408ba447018SVictor Perevertkin
2409ba447018SVictor Perevertkin /* We're done with the remote database */
2410ba447018SVictor Perevertkin CloseRemoteDatabase(RemoteDatabase);
2411ba447018SVictor Perevertkin
2412ba447018SVictor Perevertkin /* Check we were find writing the entry */
2413ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2414ba447018SVictor Perevertkin {
2415ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2416ba447018SVictor Perevertkin return Status;
2417ba447018SVictor Perevertkin }
2418ba447018SVictor Perevertkin
2419ba447018SVictor Perevertkin /* This is the end, allocate an associated entry */
2420ba447018SVictor Perevertkin AssociatedEntry = AllocatePool(sizeof(ASSOCIATED_DEVICE_ENTRY));
2421ba447018SVictor Perevertkin if (AssociatedEntry == NULL)
2422ba447018SVictor Perevertkin {
2423ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2424ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
2425ba447018SVictor Perevertkin }
2426ba447018SVictor Perevertkin
2427ba447018SVictor Perevertkin /* Initialize its source name string */
2428ba447018SVictor Perevertkin AssociatedEntry->String.Length = SourceSymbolicName.Length;
2429ba447018SVictor Perevertkin AssociatedEntry->String.MaximumLength = AssociatedEntry->String.Length + sizeof(UNICODE_NULL);
2430ba447018SVictor Perevertkin AssociatedEntry->String.Buffer = AllocatePool(AssociatedEntry->String.MaximumLength);
2431ba447018SVictor Perevertkin if (AssociatedEntry->String.Buffer == NULL)
2432ba447018SVictor Perevertkin {
2433ba447018SVictor Perevertkin FreePool(AssociatedEntry);
2434ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2435ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
2436ba447018SVictor Perevertkin }
2437ba447018SVictor Perevertkin
2438ba447018SVictor Perevertkin /* Copy data & insert in list */
2439ba447018SVictor Perevertkin RtlCopyMemory(AssociatedEntry->String.Buffer, SourceSymbolicName.Buffer, SourceSymbolicName.Length);
2440ba447018SVictor Perevertkin AssociatedEntry->String.Buffer[SourceSymbolicName.Length / sizeof(WCHAR)] = UNICODE_NULL;
2441ba447018SVictor Perevertkin AssociatedEntry->DeviceInformation = DeviceInformation;
2442ba447018SVictor Perevertkin InsertTailList(&TargetDeviceInformation->AssociatedDevicesHead, &AssociatedEntry->AssociatedDevicesEntry);
2443ba447018SVictor Perevertkin
2444ba447018SVictor Perevertkin /* We're done! */
2445ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2446ba447018SVictor Perevertkin return STATUS_SUCCESS;
2447ba447018SVictor Perevertkin }
2448ba447018SVictor Perevertkin
2449ba447018SVictor Perevertkin /*
2450ba447018SVictor Perevertkin * @implemented
2451ba447018SVictor Perevertkin */
2452ba447018SVictor Perevertkin NTSTATUS
MountMgrVolumeMountPointDeleted(IN PDEVICE_EXTENSION DeviceExtension,IN PIRP Irp,IN NTSTATUS LockStatus)2453ba447018SVictor Perevertkin MountMgrVolumeMountPointDeleted(IN PDEVICE_EXTENSION DeviceExtension,
2454ba447018SVictor Perevertkin IN PIRP Irp,
2455ba447018SVictor Perevertkin IN NTSTATUS LockStatus)
2456ba447018SVictor Perevertkin {
2457ba447018SVictor Perevertkin LONG Offset;
2458ba447018SVictor Perevertkin NTSTATUS Status;
2459ba447018SVictor Perevertkin PLIST_ENTRY Entry;
2460ba447018SVictor Perevertkin HANDLE RemoteDatabase;
2461ba447018SVictor Perevertkin PDATABASE_ENTRY DatabaseEntry;
2462ba447018SVictor Perevertkin PUNIQUE_ID_REPLICATE UniqueIdReplicate;
2463ba447018SVictor Perevertkin PASSOCIATED_DEVICE_ENTRY AssociatedEntry;
2464ba447018SVictor Perevertkin PDEVICE_INFORMATION DeviceInformation, TargetDeviceInformation;
2465ba447018SVictor Perevertkin UNICODE_STRING LinkTarget, SourceDeviceName, SourceSymbolicName, TargetVolumeName, VolumeName, DbName;
2466ba447018SVictor Perevertkin
2467ba447018SVictor Perevertkin /* Initialize string */
2468ba447018SVictor Perevertkin LinkTarget.Length = 0;
2469ba447018SVictor Perevertkin LinkTarget.MaximumLength = 0xC8;
2470ba447018SVictor Perevertkin LinkTarget.Buffer = AllocatePool(LinkTarget.MaximumLength);
2471ba447018SVictor Perevertkin if (LinkTarget.Buffer == NULL)
2472ba447018SVictor Perevertkin {
2473ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
2474ba447018SVictor Perevertkin }
2475ba447018SVictor Perevertkin
2476ba447018SVictor Perevertkin /* If the mount point was deleted, then, it changed!
2477ba447018SVictor Perevertkin * Also use it to query some information
2478ba447018SVictor Perevertkin */
2479ba447018SVictor Perevertkin Status = MountMgrVolumeMountPointChanged(DeviceExtension, Irp, LockStatus, &SourceDeviceName, &SourceSymbolicName, &TargetVolumeName);
2480ba447018SVictor Perevertkin /* Pending means DB are under synchronization, bail out */
2481ba447018SVictor Perevertkin if (Status == STATUS_PENDING)
2482ba447018SVictor Perevertkin {
2483ba447018SVictor Perevertkin FreePool(LinkTarget.Buffer);
2484ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2485ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2486ba447018SVictor Perevertkin return STATUS_SUCCESS;
2487ba447018SVictor Perevertkin }
2488ba447018SVictor Perevertkin else if (!NT_SUCCESS(Status))
2489ba447018SVictor Perevertkin {
2490ba447018SVictor Perevertkin FreePool(LinkTarget.Buffer);
2491ba447018SVictor Perevertkin return Status;
2492ba447018SVictor Perevertkin }
2493ba447018SVictor Perevertkin
2494ba447018SVictor Perevertkin /* Query the device information */
2495ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2496ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2497ba447018SVictor Perevertkin {
2498ba447018SVictor Perevertkin /* If it failed, first try to get volume name */
2499ba447018SVictor Perevertkin Status = QueryVolumeName(0, NULL, &SourceDeviceName, &LinkTarget, &VolumeName);
2500ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2501ba447018SVictor Perevertkin {
2502ba447018SVictor Perevertkin /* Then, try to read the symlink */
2503ba447018SVictor Perevertkin Status = MountMgrQuerySymbolicLink(&SourceDeviceName, &LinkTarget);
2504ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2505ba447018SVictor Perevertkin {
2506ba447018SVictor Perevertkin FreePool(LinkTarget.Buffer);
2507ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2508ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2509ba447018SVictor Perevertkin return Status;
2510ba447018SVictor Perevertkin }
2511ba447018SVictor Perevertkin }
2512ba447018SVictor Perevertkin else
2513ba447018SVictor Perevertkin {
2514ba447018SVictor Perevertkin FreePool(VolumeName.Buffer);
2515ba447018SVictor Perevertkin }
2516ba447018SVictor Perevertkin
2517ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2518ba447018SVictor Perevertkin
2519ba447018SVictor Perevertkin SourceDeviceName.Length = LinkTarget.Length;
2520ba447018SVictor Perevertkin SourceDeviceName.MaximumLength = LinkTarget.MaximumLength;
2521ba447018SVictor Perevertkin SourceDeviceName.Buffer = LinkTarget.Buffer;
2522ba447018SVictor Perevertkin
2523ba447018SVictor Perevertkin /* Now that we have the correct source, reattempt to query information */
2524ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, &SourceDeviceName, FALSE, &DeviceInformation);
2525ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2526ba447018SVictor Perevertkin {
2527ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2528ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2529ba447018SVictor Perevertkin return Status;
2530ba447018SVictor Perevertkin }
2531ba447018SVictor Perevertkin }
2532ba447018SVictor Perevertkin
2533ba447018SVictor Perevertkin FreePool(SourceDeviceName.Buffer);
2534ba447018SVictor Perevertkin
2535ba447018SVictor Perevertkin /* Get information about target device */
2536ba447018SVictor Perevertkin Status = FindDeviceInfo(DeviceExtension, &TargetVolumeName, FALSE, &TargetDeviceInformation);
2537ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2538ba447018SVictor Perevertkin {
2539ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2540ba447018SVictor Perevertkin return Status;
2541ba447018SVictor Perevertkin }
2542ba447018SVictor Perevertkin
2543ba447018SVictor Perevertkin /* Open the remote database */
2544ba447018SVictor Perevertkin RemoteDatabase = OpenRemoteDatabase(DeviceInformation, TRUE);
2545ba447018SVictor Perevertkin if (RemoteDatabase == 0)
2546ba447018SVictor Perevertkin {
2547ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2548ba447018SVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
2549ba447018SVictor Perevertkin }
2550ba447018SVictor Perevertkin
2551ba447018SVictor Perevertkin /* Browse all the entries */
2552ba447018SVictor Perevertkin Offset = 0;
2553ba447018SVictor Perevertkin for (;;)
2554ba447018SVictor Perevertkin {
2555ba447018SVictor Perevertkin DatabaseEntry = GetRemoteDatabaseEntry(RemoteDatabase, Offset);
2556ba447018SVictor Perevertkin if (DatabaseEntry == NULL)
2557ba447018SVictor Perevertkin {
2558ba447018SVictor Perevertkin /* We didn't find ourselves, that's infortunate! */
2559ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2560ba447018SVictor Perevertkin CloseRemoteDatabase(RemoteDatabase);
2561ba447018SVictor Perevertkin return STATUS_INVALID_PARAMETER;
2562ba447018SVictor Perevertkin }
2563ba447018SVictor Perevertkin
2564ba447018SVictor Perevertkin /* Try to find ourselves */
2565ba447018SVictor Perevertkin DbName.MaximumLength = DatabaseEntry->SymbolicNameLength;
2566ba447018SVictor Perevertkin DbName.Length = DbName.MaximumLength;
2567ba447018SVictor Perevertkin DbName.Buffer = (PWSTR)((ULONG_PTR)DatabaseEntry + DatabaseEntry->SymbolicNameOffset);
2568ba447018SVictor Perevertkin if (RtlEqualUnicodeString(&TargetVolumeName, &DbName, TRUE))
2569ba447018SVictor Perevertkin {
2570ba447018SVictor Perevertkin break;
2571ba447018SVictor Perevertkin }
2572ba447018SVictor Perevertkin
2573ba447018SVictor Perevertkin Offset += DatabaseEntry->EntrySize;
2574ba447018SVictor Perevertkin FreePool(DatabaseEntry);
2575ba447018SVictor Perevertkin }
2576ba447018SVictor Perevertkin
2577ba447018SVictor Perevertkin /* Dereference ourselves */
2578ba447018SVictor Perevertkin DatabaseEntry->EntryReferences--;
2579ba447018SVictor Perevertkin if (DatabaseEntry->EntryReferences == 0)
2580ba447018SVictor Perevertkin {
2581ba447018SVictor Perevertkin /* If we're still referenced, just update the entry */
2582ba447018SVictor Perevertkin Status = WriteRemoteDatabaseEntry(RemoteDatabase, Offset, DatabaseEntry);
2583ba447018SVictor Perevertkin }
2584ba447018SVictor Perevertkin else
2585ba447018SVictor Perevertkin {
2586ba447018SVictor Perevertkin /* Otherwise, delete the entry */
2587ba447018SVictor Perevertkin Status = DeleteRemoteDatabaseEntry(RemoteDatabase, Offset);
2588ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2589ba447018SVictor Perevertkin {
2590ba447018SVictor Perevertkin FreePool(DatabaseEntry);
2591ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2592ba447018SVictor Perevertkin CloseRemoteDatabase(RemoteDatabase);
2593ba447018SVictor Perevertkin return Status;
2594ba447018SVictor Perevertkin }
2595ba447018SVictor Perevertkin
2596ba447018SVictor Perevertkin /* Also, delete our unique ID replicated record */
2597ba447018SVictor Perevertkin for (Entry = DeviceInformation->ReplicatedUniqueIdsListHead.Flink;
2598ba447018SVictor Perevertkin Entry != &DeviceInformation->ReplicatedUniqueIdsListHead;
2599ba447018SVictor Perevertkin Entry = Entry->Flink)
2600ba447018SVictor Perevertkin {
2601ba447018SVictor Perevertkin UniqueIdReplicate = CONTAINING_RECORD(Entry, UNIQUE_ID_REPLICATE, ReplicatedUniqueIdsListEntry);
2602ba447018SVictor Perevertkin
2603ba447018SVictor Perevertkin if (UniqueIdReplicate->UniqueId->UniqueIdLength == DatabaseEntry->UniqueIdLength &&
2604ba447018SVictor Perevertkin RtlCompareMemory(UniqueIdReplicate->UniqueId->UniqueId,
2605ba447018SVictor Perevertkin (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
2606ba447018SVictor Perevertkin DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
2607ba447018SVictor Perevertkin {
2608ba447018SVictor Perevertkin break;
2609ba447018SVictor Perevertkin }
2610ba447018SVictor Perevertkin }
2611ba447018SVictor Perevertkin
2612ba447018SVictor Perevertkin /* It has to exist! */
2613ba447018SVictor Perevertkin if (Entry == &DeviceInformation->ReplicatedUniqueIdsListHead)
2614ba447018SVictor Perevertkin {
2615ba447018SVictor Perevertkin FreePool(DatabaseEntry);
2616ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2617ba447018SVictor Perevertkin CloseRemoteDatabase(RemoteDatabase);
2618ba447018SVictor Perevertkin return STATUS_UNSUCCESSFUL;
2619ba447018SVictor Perevertkin }
2620ba447018SVictor Perevertkin
2621ba447018SVictor Perevertkin /* Remove it and free it */
2622ba447018SVictor Perevertkin RemoveEntryList(&UniqueIdReplicate->ReplicatedUniqueIdsListEntry);
2623ba447018SVictor Perevertkin FreePool(UniqueIdReplicate->UniqueId);
2624ba447018SVictor Perevertkin FreePool(UniqueIdReplicate);
2625ba447018SVictor Perevertkin }
2626ba447018SVictor Perevertkin
2627ba447018SVictor Perevertkin /* We're done with the remote database */
2628ba447018SVictor Perevertkin FreePool(DatabaseEntry);
2629ba447018SVictor Perevertkin CloseRemoteDatabase(RemoteDatabase);
2630ba447018SVictor Perevertkin
2631ba447018SVictor Perevertkin /* Check write operation succeed */
2632ba447018SVictor Perevertkin if (!NT_SUCCESS(Status))
2633ba447018SVictor Perevertkin {
2634ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2635ba447018SVictor Perevertkin return Status;
2636ba447018SVictor Perevertkin }
2637ba447018SVictor Perevertkin
2638ba447018SVictor Perevertkin /* Try to find our associated device entry */
2639ba447018SVictor Perevertkin for (Entry = TargetDeviceInformation->AssociatedDevicesHead.Flink;
2640ba447018SVictor Perevertkin Entry != &TargetDeviceInformation->AssociatedDevicesHead;
2641ba447018SVictor Perevertkin Entry = Entry->Flink)
2642ba447018SVictor Perevertkin {
2643ba447018SVictor Perevertkin AssociatedEntry = CONTAINING_RECORD(Entry, ASSOCIATED_DEVICE_ENTRY, AssociatedDevicesEntry);
2644ba447018SVictor Perevertkin
2645ba447018SVictor Perevertkin /* If found, delete it */
2646ba447018SVictor Perevertkin if (AssociatedEntry->DeviceInformation == DeviceInformation &&
2647ba447018SVictor Perevertkin RtlEqualUnicodeString(&AssociatedEntry->String, &SourceSymbolicName, TRUE))
2648ba447018SVictor Perevertkin {
2649ba447018SVictor Perevertkin RemoveEntryList(&AssociatedEntry->AssociatedDevicesEntry);
2650ba447018SVictor Perevertkin FreePool(AssociatedEntry->String.Buffer);
2651ba447018SVictor Perevertkin FreePool(AssociatedEntry);
2652ba447018SVictor Perevertkin break;
2653ba447018SVictor Perevertkin }
2654ba447018SVictor Perevertkin }
2655ba447018SVictor Perevertkin
2656ba447018SVictor Perevertkin /* We're done! */
2657ba447018SVictor Perevertkin FreePool(SourceSymbolicName.Buffer);
2658ba447018SVictor Perevertkin return STATUS_SUCCESS;
2659ba447018SVictor Perevertkin }
2660ba447018SVictor Perevertkin
2661ba447018SVictor Perevertkin /*
2662ba447018SVictor Perevertkin * @implemented
2663ba447018SVictor Perevertkin */
2664ba447018SVictor Perevertkin NTSTATUS
2665ba447018SVictor Perevertkin NTAPI
MountMgrDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)2666ba447018SVictor Perevertkin MountMgrDeviceControl(IN PDEVICE_OBJECT DeviceObject,
2667ba447018SVictor Perevertkin IN PIRP Irp)
2668ba447018SVictor Perevertkin {
2669ba447018SVictor Perevertkin PIO_STACK_LOCATION Stack;
2670ba447018SVictor Perevertkin NTSTATUS Status, LockStatus;
2671ba447018SVictor Perevertkin PDEVICE_EXTENSION DeviceExtension;
2672ba447018SVictor Perevertkin
2673ba447018SVictor Perevertkin Stack = IoGetCurrentIrpStackLocation(Irp);
2674ba447018SVictor Perevertkin DeviceExtension = DeviceObject->DeviceExtension;
2675ba447018SVictor Perevertkin
2676ba447018SVictor Perevertkin KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2677ba447018SVictor Perevertkin
2678ba447018SVictor Perevertkin switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2679ba447018SVictor Perevertkin {
2680ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_CREATE_POINT:
2681ba447018SVictor Perevertkin Status = MountMgrCreatePoint(DeviceExtension, Irp);
2682ba447018SVictor Perevertkin break;
2683ba447018SVictor Perevertkin
2684ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_DELETE_POINTS:
2685ba447018SVictor Perevertkin Status = MountMgrDeletePoints(DeviceExtension, Irp);
2686ba447018SVictor Perevertkin break;
2687ba447018SVictor Perevertkin
2688ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_QUERY_POINTS:
2689ba447018SVictor Perevertkin Status = MountMgrQueryPoints(DeviceExtension, Irp);
2690ba447018SVictor Perevertkin break;
2691ba447018SVictor Perevertkin
2692ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY:
2693ba447018SVictor Perevertkin Status = MountMgrDeletePointsDbOnly(DeviceExtension, Irp);
2694ba447018SVictor Perevertkin break;
2695ba447018SVictor Perevertkin
2696ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER:
2697ba447018SVictor Perevertkin Status = MountMgrNextDriveLetter(DeviceExtension, Irp);
2698ba447018SVictor Perevertkin break;
2699ba447018SVictor Perevertkin
2700ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS:
2701*5f263560SHermès Bélusca-Maïto // NOTE: On Win7+, this is handled during driver re-initialization.
2702ba447018SVictor Perevertkin DeviceExtension->AutomaticDriveLetter = TRUE;
2703ba447018SVictor Perevertkin MountMgrAssignDriveLetters(DeviceExtension);
2704ba447018SVictor Perevertkin ReconcileAllDatabasesWithMaster(DeviceExtension);
2705ba447018SVictor Perevertkin WaitForOnlinesToComplete(DeviceExtension);
2706*5f263560SHermès Bélusca-Maïto Status = STATUS_SUCCESS;
2707ba447018SVictor Perevertkin break;
2708ba447018SVictor Perevertkin
2709ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED:
2710ba447018SVictor Perevertkin KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2711ba447018SVictor Perevertkin
2712ba447018SVictor Perevertkin LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2713ba447018SVictor Perevertkin KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2714ba447018SVictor Perevertkin Status = MountMgrVolumeMountPointCreated(DeviceExtension, Irp, LockStatus);
2715ba447018SVictor Perevertkin if (NT_SUCCESS(LockStatus))
2716ba447018SVictor Perevertkin {
2717ba447018SVictor Perevertkin ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2718ba447018SVictor Perevertkin }
2719ba447018SVictor Perevertkin
2720ba447018SVictor Perevertkin break;
2721ba447018SVictor Perevertkin
2722ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED:
2723ba447018SVictor Perevertkin KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2724ba447018SVictor Perevertkin
2725ba447018SVictor Perevertkin LockStatus = WaitForRemoteDatabaseSemaphore(DeviceExtension);
2726ba447018SVictor Perevertkin KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
2727ba447018SVictor Perevertkin Status = MountMgrVolumeMountPointDeleted(DeviceExtension, Irp, LockStatus);
2728ba447018SVictor Perevertkin if (NT_SUCCESS(LockStatus))
2729ba447018SVictor Perevertkin {
2730ba447018SVictor Perevertkin ReleaseRemoteDatabaseSemaphore(DeviceExtension);
2731ba447018SVictor Perevertkin }
2732ba447018SVictor Perevertkin
2733ba447018SVictor Perevertkin break;
2734ba447018SVictor Perevertkin
2735ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_CHANGE_NOTIFY:
2736ba447018SVictor Perevertkin Status = MountMgrChangeNotify(DeviceExtension, Irp);
2737ba447018SVictor Perevertkin break;
2738ba447018SVictor Perevertkin
2739ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE:
2740ba447018SVictor Perevertkin Status = MountMgrKeepLinksWhenOffline(DeviceExtension, Irp);
2741ba447018SVictor Perevertkin break;
2742ba447018SVictor Perevertkin
2743ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES:
2744ba447018SVictor Perevertkin Status = MountMgrCheckUnprocessedVolumes(DeviceExtension, Irp);
2745ba447018SVictor Perevertkin goto Complete;
2746ba447018SVictor Perevertkin
2747ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION:
2748ba447018SVictor Perevertkin KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2749ba447018SVictor Perevertkin Status = MountMgrVolumeArrivalNotification(DeviceExtension, Irp);
2750ba447018SVictor Perevertkin goto Complete;
2751ba447018SVictor Perevertkin
2752ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH:
2753ba447018SVictor Perevertkin Status = MountMgrQueryDosVolumePath(DeviceExtension, Irp);
2754ba447018SVictor Perevertkin break;
2755ba447018SVictor Perevertkin
2756ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS:
2757ba447018SVictor Perevertkin Status = MountMgrQueryDosVolumePaths(DeviceExtension, Irp);
2758ba447018SVictor Perevertkin break;
2759ba447018SVictor Perevertkin
2760ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_SCRUB_REGISTRY:
2761ba447018SVictor Perevertkin Status = MountMgrScrubRegistry(DeviceExtension);
2762ba447018SVictor Perevertkin break;
2763ba447018SVictor Perevertkin
2764ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT:
2765ba447018SVictor Perevertkin Status = MountMgrQueryAutoMount(DeviceExtension, Irp);
2766ba447018SVictor Perevertkin break;
2767ba447018SVictor Perevertkin
2768ba447018SVictor Perevertkin case IOCTL_MOUNTMGR_SET_AUTO_MOUNT:
2769ba447018SVictor Perevertkin Status = MountMgrSetAutoMount(DeviceExtension, Irp);
2770ba447018SVictor Perevertkin break;
2771ba447018SVictor Perevertkin
2772ba447018SVictor Perevertkin default:
2773ba447018SVictor Perevertkin Status = STATUS_INVALID_DEVICE_REQUEST;
2774ba447018SVictor Perevertkin }
2775ba447018SVictor Perevertkin
2776ba447018SVictor Perevertkin KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
2777ba447018SVictor Perevertkin
2778ba447018SVictor Perevertkin if (Status != STATUS_PENDING)
2779ba447018SVictor Perevertkin {
2780ba447018SVictor Perevertkin goto Complete;
2781ba447018SVictor Perevertkin }
2782ba447018SVictor Perevertkin
2783ba447018SVictor Perevertkin return Status;
2784ba447018SVictor Perevertkin
2785ba447018SVictor Perevertkin Complete:
2786ba447018SVictor Perevertkin Irp->IoStatus.Status = Status;
2787ba447018SVictor Perevertkin IoCompleteRequest(Irp, IO_NO_INCREMENT);
2788ba447018SVictor Perevertkin
2789ba447018SVictor Perevertkin return Status;
2790ba447018SVictor Perevertkin }
2791