xref: /reactos/drivers/storage/mountmgr/device.c (revision 5f263560)
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