xref: /reactos/drivers/storage/mountmgr/uniqueid.c (revision ba447018)
1*ba447018SVictor Perevertkin /*
2*ba447018SVictor Perevertkin  *  ReactOS kernel
3*ba447018SVictor Perevertkin  *  Copyright (C) 2011 ReactOS Team
4*ba447018SVictor Perevertkin  *
5*ba447018SVictor Perevertkin  *  This program is free software; you can redistribute it and/or modify
6*ba447018SVictor Perevertkin  *  it under the terms of the GNU General Public License as published by
7*ba447018SVictor Perevertkin  *  the Free Software Foundation; either version 2 of the License, or
8*ba447018SVictor Perevertkin  *  (at your option) any later version.
9*ba447018SVictor Perevertkin  *
10*ba447018SVictor Perevertkin  *  This program is distributed in the hope that it will be useful,
11*ba447018SVictor Perevertkin  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12*ba447018SVictor Perevertkin  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*ba447018SVictor Perevertkin  *  GNU General Public License for more details.
14*ba447018SVictor Perevertkin  *
15*ba447018SVictor Perevertkin  *  You should have received a copy of the GNU General Public License
16*ba447018SVictor Perevertkin  *  along with this program; if not, write to the Free Software
17*ba447018SVictor Perevertkin  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18*ba447018SVictor Perevertkin  *
19*ba447018SVictor Perevertkin  * COPYRIGHT:        See COPYING in the top level directory
20*ba447018SVictor Perevertkin  * PROJECT:          ReactOS kernel
21*ba447018SVictor Perevertkin  * FILE:             drivers/filesystem/mountmgr/uniqueid.c
22*ba447018SVictor Perevertkin  * PURPOSE:          Mount Manager - Unique ID
23*ba447018SVictor Perevertkin  * PROGRAMMER:       Pierre Schweitzer (pierre.schweitzer@reactos.org)
24*ba447018SVictor Perevertkin  */
25*ba447018SVictor Perevertkin 
26*ba447018SVictor Perevertkin #include "mntmgr.h"
27*ba447018SVictor Perevertkin 
28*ba447018SVictor Perevertkin #define NDEBUG
29*ba447018SVictor Perevertkin #include <debug.h>
30*ba447018SVictor Perevertkin 
31*ba447018SVictor Perevertkin /*
32*ba447018SVictor Perevertkin  * @implemented
33*ba447018SVictor Perevertkin  */
34*ba447018SVictor Perevertkin NTSTATUS
35*ba447018SVictor Perevertkin NTAPI
ChangeUniqueIdRoutine(IN PWSTR ValueName,IN ULONG ValueType,IN PVOID ValueData,IN ULONG ValueLength,IN PVOID Context,IN PVOID EntryContext)36*ba447018SVictor Perevertkin ChangeUniqueIdRoutine(IN PWSTR ValueName,
37*ba447018SVictor Perevertkin                       IN ULONG ValueType,
38*ba447018SVictor Perevertkin                       IN PVOID ValueData,
39*ba447018SVictor Perevertkin                       IN ULONG ValueLength,
40*ba447018SVictor Perevertkin                       IN PVOID Context,
41*ba447018SVictor Perevertkin                       IN PVOID EntryContext)
42*ba447018SVictor Perevertkin {
43*ba447018SVictor Perevertkin     PMOUNTDEV_UNIQUE_ID OldUniqueId = Context;
44*ba447018SVictor Perevertkin     PMOUNTDEV_UNIQUE_ID NewUniqueId = EntryContext;
45*ba447018SVictor Perevertkin 
46*ba447018SVictor Perevertkin     /* Validate parameters not to corrupt registry */
47*ba447018SVictor Perevertkin     if ((ValueType != REG_BINARY) ||
48*ba447018SVictor Perevertkin         (OldUniqueId->UniqueIdLength != ValueLength))
49*ba447018SVictor Perevertkin     {
50*ba447018SVictor Perevertkin         return STATUS_SUCCESS;
51*ba447018SVictor Perevertkin     }
52*ba447018SVictor Perevertkin 
53*ba447018SVictor Perevertkin     if (RtlCompareMemory(OldUniqueId->UniqueId, ValueData, ValueLength) == ValueLength)
54*ba447018SVictor Perevertkin     {
55*ba447018SVictor Perevertkin         /* Write new data */
56*ba447018SVictor Perevertkin         RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
57*ba447018SVictor Perevertkin                               DatabasePath,
58*ba447018SVictor Perevertkin                               ValueName,
59*ba447018SVictor Perevertkin                               REG_BINARY,
60*ba447018SVictor Perevertkin                               NewUniqueId,
61*ba447018SVictor Perevertkin                               NewUniqueId->UniqueIdLength);
62*ba447018SVictor Perevertkin     }
63*ba447018SVictor Perevertkin 
64*ba447018SVictor Perevertkin     return STATUS_SUCCESS;
65*ba447018SVictor Perevertkin }
66*ba447018SVictor Perevertkin 
67*ba447018SVictor Perevertkin /*
68*ba447018SVictor Perevertkin  * @implemented
69*ba447018SVictor Perevertkin  */
70*ba447018SVictor Perevertkin VOID
MountMgrUniqueIdChangeRoutine(IN PDEVICE_EXTENSION DeviceExtension,IN PMOUNTDEV_UNIQUE_ID OldUniqueId,IN PMOUNTDEV_UNIQUE_ID NewUniqueId)71*ba447018SVictor Perevertkin MountMgrUniqueIdChangeRoutine(IN PDEVICE_EXTENSION DeviceExtension,
72*ba447018SVictor Perevertkin                               IN PMOUNTDEV_UNIQUE_ID OldUniqueId,
73*ba447018SVictor Perevertkin                               IN PMOUNTDEV_UNIQUE_ID NewUniqueId)
74*ba447018SVictor Perevertkin {
75*ba447018SVictor Perevertkin     NTSTATUS Status;
76*ba447018SVictor Perevertkin     BOOLEAN ResyncNeeded;
77*ba447018SVictor Perevertkin     PUNIQUE_ID_REPLICATE DuplicateId;
78*ba447018SVictor Perevertkin     PDEVICE_INFORMATION DeviceInformation;
79*ba447018SVictor Perevertkin     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
80*ba447018SVictor Perevertkin     PMOUNTDEV_UNIQUE_ID UniqueId, NewDuplicateId;
81*ba447018SVictor Perevertkin     PLIST_ENTRY ListHead, NextEntry, ReplicatedHead, NextReplicated;
82*ba447018SVictor Perevertkin 
83*ba447018SVictor Perevertkin     /* Synchronise with remote databases */
84*ba447018SVictor Perevertkin     Status = WaitForRemoteDatabaseSemaphore(DeviceExtension);
85*ba447018SVictor Perevertkin     KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
86*ba447018SVictor Perevertkin 
87*ba447018SVictor Perevertkin     RtlZeroMemory(QueryTable, sizeof(QueryTable));
88*ba447018SVictor Perevertkin     QueryTable[0].QueryRoutine = ChangeUniqueIdRoutine;
89*ba447018SVictor Perevertkin     QueryTable[0].EntryContext = NewUniqueId;
90*ba447018SVictor Perevertkin 
91*ba447018SVictor Perevertkin     /* Write new data */
92*ba447018SVictor Perevertkin     RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
93*ba447018SVictor Perevertkin                            DatabasePath,
94*ba447018SVictor Perevertkin                            QueryTable,
95*ba447018SVictor Perevertkin                            OldUniqueId,
96*ba447018SVictor Perevertkin                            NULL);
97*ba447018SVictor Perevertkin 
98*ba447018SVictor Perevertkin     /* Browse all the devices to find the one that
99*ba447018SVictor Perevertkin      * owns the old unique ID
100*ba447018SVictor Perevertkin      */
101*ba447018SVictor Perevertkin     ListHead = &(DeviceExtension->DeviceListHead);
102*ba447018SVictor Perevertkin     NextEntry = ListHead->Flink;
103*ba447018SVictor Perevertkin     while (ListHead != NextEntry)
104*ba447018SVictor Perevertkin     {
105*ba447018SVictor Perevertkin         DeviceInformation = CONTAINING_RECORD(NextEntry,
106*ba447018SVictor Perevertkin                                               DEVICE_INFORMATION,
107*ba447018SVictor Perevertkin                                               DeviceListEntry);
108*ba447018SVictor Perevertkin 
109*ba447018SVictor Perevertkin         if (DeviceInformation->UniqueId->UniqueIdLength == OldUniqueId->UniqueIdLength &&
110*ba447018SVictor Perevertkin             RtlCompareMemory(OldUniqueId->UniqueId,
111*ba447018SVictor Perevertkin                              DeviceInformation->UniqueId->UniqueId,
112*ba447018SVictor Perevertkin                              OldUniqueId->UniqueIdLength) == OldUniqueId->UniqueIdLength)
113*ba447018SVictor Perevertkin         {
114*ba447018SVictor Perevertkin             break;
115*ba447018SVictor Perevertkin         }
116*ba447018SVictor Perevertkin 
117*ba447018SVictor Perevertkin         NextEntry = NextEntry->Flink;
118*ba447018SVictor Perevertkin     }
119*ba447018SVictor Perevertkin 
120*ba447018SVictor Perevertkin     /* If we didn't find any release everything and quit */
121*ba447018SVictor Perevertkin     if (ListHead == NextEntry)
122*ba447018SVictor Perevertkin     {
123*ba447018SVictor Perevertkin         KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
124*ba447018SVictor Perevertkin                            1, FALSE);
125*ba447018SVictor Perevertkin 
126*ba447018SVictor Perevertkin         if (NT_SUCCESS(Status))
127*ba447018SVictor Perevertkin         {
128*ba447018SVictor Perevertkin             ReleaseRemoteDatabaseSemaphore(DeviceExtension);
129*ba447018SVictor Perevertkin         }
130*ba447018SVictor Perevertkin 
131*ba447018SVictor Perevertkin         return;
132*ba447018SVictor Perevertkin     }
133*ba447018SVictor Perevertkin 
134*ba447018SVictor Perevertkin     /* If lock failed, then, just update this database */
135*ba447018SVictor Perevertkin     if (!NT_SUCCESS(Status))
136*ba447018SVictor Perevertkin     {
137*ba447018SVictor Perevertkin         ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
138*ba447018SVictor Perevertkin         KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
139*ba447018SVictor Perevertkin                            1, FALSE);
140*ba447018SVictor Perevertkin         return;
141*ba447018SVictor Perevertkin     }
142*ba447018SVictor Perevertkin 
143*ba447018SVictor Perevertkin     /* Allocate new unique ID */
144*ba447018SVictor Perevertkin     UniqueId = AllocatePool(NewUniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
145*ba447018SVictor Perevertkin     if (!UniqueId)
146*ba447018SVictor Perevertkin     {
147*ba447018SVictor Perevertkin         KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
148*ba447018SVictor Perevertkin                            1, FALSE);
149*ba447018SVictor Perevertkin         ReleaseRemoteDatabaseSemaphore(DeviceExtension);
150*ba447018SVictor Perevertkin         return;
151*ba447018SVictor Perevertkin     }
152*ba447018SVictor Perevertkin 
153*ba447018SVictor Perevertkin     /* Release old one */
154*ba447018SVictor Perevertkin     FreePool(DeviceInformation->UniqueId);
155*ba447018SVictor Perevertkin     /* And set new one */
156*ba447018SVictor Perevertkin     DeviceInformation->UniqueId = UniqueId;
157*ba447018SVictor Perevertkin     UniqueId->UniqueIdLength = NewUniqueId->UniqueIdLength;
158*ba447018SVictor Perevertkin     RtlCopyMemory(UniqueId->UniqueId, NewUniqueId->UniqueId, NewUniqueId->UniqueIdLength);
159*ba447018SVictor Perevertkin 
160*ba447018SVictor Perevertkin     /* Now, check if it's required to update replicated unique IDs as well */
161*ba447018SVictor Perevertkin     ListHead = &(DeviceExtension->DeviceListHead);
162*ba447018SVictor Perevertkin     NextEntry = ListHead->Flink;
163*ba447018SVictor Perevertkin     while (ListHead != NextEntry)
164*ba447018SVictor Perevertkin     {
165*ba447018SVictor Perevertkin         DeviceInformation = CONTAINING_RECORD(NextEntry,
166*ba447018SVictor Perevertkin                                               DEVICE_INFORMATION,
167*ba447018SVictor Perevertkin                                               DeviceListEntry);
168*ba447018SVictor Perevertkin         ResyncNeeded = FALSE;
169*ba447018SVictor Perevertkin 
170*ba447018SVictor Perevertkin         ReplicatedHead = &(DeviceInformation->ReplicatedUniqueIdsListHead);
171*ba447018SVictor Perevertkin         NextReplicated = ReplicatedHead->Flink;
172*ba447018SVictor Perevertkin         while (ReplicatedHead != NextReplicated)
173*ba447018SVictor Perevertkin         {
174*ba447018SVictor Perevertkin             DuplicateId = CONTAINING_RECORD(NextReplicated,
175*ba447018SVictor Perevertkin                                             UNIQUE_ID_REPLICATE,
176*ba447018SVictor Perevertkin                                             ReplicatedUniqueIdsListEntry);
177*ba447018SVictor Perevertkin 
178*ba447018SVictor Perevertkin             if (DuplicateId->UniqueId->UniqueIdLength == OldUniqueId->UniqueIdLength)
179*ba447018SVictor Perevertkin             {
180*ba447018SVictor Perevertkin                 if (RtlCompareMemory(DuplicateId->UniqueId->UniqueId,
181*ba447018SVictor Perevertkin                                      OldUniqueId->UniqueId,
182*ba447018SVictor Perevertkin                                      OldUniqueId->UniqueIdLength) == OldUniqueId->UniqueIdLength)
183*ba447018SVictor Perevertkin                 {
184*ba447018SVictor Perevertkin                     /* It was our old unique ID */
185*ba447018SVictor Perevertkin                     NewDuplicateId = AllocatePool(NewUniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
186*ba447018SVictor Perevertkin                     if (NewDuplicateId)
187*ba447018SVictor Perevertkin                     {
188*ba447018SVictor Perevertkin                         /* Update it */
189*ba447018SVictor Perevertkin                         ResyncNeeded = TRUE;
190*ba447018SVictor Perevertkin                         FreePool(DuplicateId->UniqueId);
191*ba447018SVictor Perevertkin 
192*ba447018SVictor Perevertkin                         DuplicateId->UniqueId = NewDuplicateId;
193*ba447018SVictor Perevertkin                         DuplicateId->UniqueId->UniqueIdLength = NewUniqueId->UniqueIdLength;
194*ba447018SVictor Perevertkin                         RtlCopyMemory(NewDuplicateId->UniqueId, NewUniqueId->UniqueId, NewUniqueId->UniqueIdLength);
195*ba447018SVictor Perevertkin                     }
196*ba447018SVictor Perevertkin                 }
197*ba447018SVictor Perevertkin             }
198*ba447018SVictor Perevertkin 
199*ba447018SVictor Perevertkin             NextReplicated = NextReplicated->Flink;
200*ba447018SVictor Perevertkin         }
201*ba447018SVictor Perevertkin 
202*ba447018SVictor Perevertkin         /* If resync is required on this device, do it */
203*ba447018SVictor Perevertkin         if (ResyncNeeded)
204*ba447018SVictor Perevertkin         {
205*ba447018SVictor Perevertkin             ChangeRemoteDatabaseUniqueId(DeviceInformation, OldUniqueId, NewUniqueId);
206*ba447018SVictor Perevertkin         }
207*ba447018SVictor Perevertkin 
208*ba447018SVictor Perevertkin         NextEntry = NextEntry->Flink;
209*ba447018SVictor Perevertkin     }
210*ba447018SVictor Perevertkin 
211*ba447018SVictor Perevertkin     KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
212*ba447018SVictor Perevertkin     ReleaseRemoteDatabaseSemaphore(DeviceExtension);
213*ba447018SVictor Perevertkin 
214*ba447018SVictor Perevertkin     return;
215*ba447018SVictor Perevertkin }
216*ba447018SVictor Perevertkin 
217*ba447018SVictor Perevertkin /*
218*ba447018SVictor Perevertkin  * @implemented
219*ba447018SVictor Perevertkin  */
220*ba447018SVictor Perevertkin BOOLEAN
IsUniqueIdPresent(IN PDEVICE_EXTENSION DeviceExtension,IN PDATABASE_ENTRY DatabaseEntry)221*ba447018SVictor Perevertkin IsUniqueIdPresent(IN PDEVICE_EXTENSION DeviceExtension,
222*ba447018SVictor Perevertkin                   IN PDATABASE_ENTRY DatabaseEntry)
223*ba447018SVictor Perevertkin {
224*ba447018SVictor Perevertkin     PLIST_ENTRY NextEntry;
225*ba447018SVictor Perevertkin     PDEVICE_INFORMATION DeviceInformation;
226*ba447018SVictor Perevertkin 
227*ba447018SVictor Perevertkin     /* If no device, no unique ID (O'rly?!)
228*ba447018SVictor Perevertkin      * ./)/).
229*ba447018SVictor Perevertkin      * (°-°)
230*ba447018SVictor Perevertkin      * (___) ORLY?
231*ba447018SVictor Perevertkin      *  " "
232*ba447018SVictor Perevertkin      */
233*ba447018SVictor Perevertkin     if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
234*ba447018SVictor Perevertkin     {
235*ba447018SVictor Perevertkin         return FALSE;
236*ba447018SVictor Perevertkin     }
237*ba447018SVictor Perevertkin 
238*ba447018SVictor Perevertkin     /* Now we know that we have devices, find the one */
239*ba447018SVictor Perevertkin     for (NextEntry = DeviceExtension->DeviceListHead.Flink;
240*ba447018SVictor Perevertkin          NextEntry != &(DeviceExtension->DeviceListHead);
241*ba447018SVictor Perevertkin          NextEntry = NextEntry->Flink)
242*ba447018SVictor Perevertkin     {
243*ba447018SVictor Perevertkin         DeviceInformation = CONTAINING_RECORD(NextEntry,
244*ba447018SVictor Perevertkin                                               DEVICE_INFORMATION,
245*ba447018SVictor Perevertkin                                               DeviceListEntry);
246*ba447018SVictor Perevertkin 
247*ba447018SVictor Perevertkin         if (DeviceInformation->UniqueId->UniqueIdLength != DatabaseEntry->UniqueIdLength)
248*ba447018SVictor Perevertkin         {
249*ba447018SVictor Perevertkin             continue;
250*ba447018SVictor Perevertkin         }
251*ba447018SVictor Perevertkin 
252*ba447018SVictor Perevertkin         /* It's matching! */
253*ba447018SVictor Perevertkin         if (RtlCompareMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
254*ba447018SVictor Perevertkin                              DeviceInformation->UniqueId->UniqueId,
255*ba447018SVictor Perevertkin                              DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
256*ba447018SVictor Perevertkin         {
257*ba447018SVictor Perevertkin             return TRUE;
258*ba447018SVictor Perevertkin         }
259*ba447018SVictor Perevertkin     }
260*ba447018SVictor Perevertkin 
261*ba447018SVictor Perevertkin     /* No luck... */
262*ba447018SVictor Perevertkin     return FALSE;
263*ba447018SVictor Perevertkin }
264*ba447018SVictor Perevertkin 
265*ba447018SVictor Perevertkin /*
266*ba447018SVictor Perevertkin  * @implemented
267*ba447018SVictor Perevertkin  */
268*ba447018SVictor Perevertkin VOID
CreateNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)269*ba447018SVictor Perevertkin CreateNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
270*ba447018SVictor Perevertkin {
271*ba447018SVictor Perevertkin     UUID Guid;
272*ba447018SVictor Perevertkin     PWCHAR String;
273*ba447018SVictor Perevertkin     UNICODE_STRING GuidString;
274*ba447018SVictor Perevertkin 
275*ba447018SVictor Perevertkin     /* Entry with no drive letter are made that way:
276*ba447018SVictor Perevertkin      * Instead of having a path with the letter,
277*ba447018SVictor Perevertkin      * you have GUID with the unique ID.
278*ba447018SVictor Perevertkin      */
279*ba447018SVictor Perevertkin     if (!NT_SUCCESS(ExUuidCreate(&Guid)))
280*ba447018SVictor Perevertkin     {
281*ba447018SVictor Perevertkin         return;
282*ba447018SVictor Perevertkin     }
283*ba447018SVictor Perevertkin 
284*ba447018SVictor Perevertkin     /* Convert to string */
285*ba447018SVictor Perevertkin     if (!NT_SUCCESS(RtlStringFromGUID(&Guid, &GuidString)))
286*ba447018SVictor Perevertkin     {
287*ba447018SVictor Perevertkin         return;
288*ba447018SVictor Perevertkin     }
289*ba447018SVictor Perevertkin 
290*ba447018SVictor Perevertkin     /* No letter entries must start with #, so allocate a proper string */
291*ba447018SVictor Perevertkin     String = AllocatePool(GuidString.Length + 2 * sizeof(WCHAR));
292*ba447018SVictor Perevertkin     if (!String)
293*ba447018SVictor Perevertkin     {
294*ba447018SVictor Perevertkin         ExFreePoolWithTag(GuidString.Buffer, 0);
295*ba447018SVictor Perevertkin         return;
296*ba447018SVictor Perevertkin     }
297*ba447018SVictor Perevertkin 
298*ba447018SVictor Perevertkin     /* Write the complete string */
299*ba447018SVictor Perevertkin     String[0] = L'#';
300*ba447018SVictor Perevertkin     RtlCopyMemory(String + 1, GuidString.Buffer, GuidString.Length);
301*ba447018SVictor Perevertkin     String[GuidString.Length / sizeof(WCHAR)] = UNICODE_NULL;
302*ba447018SVictor Perevertkin 
303*ba447018SVictor Perevertkin     /* Don't need that one anymore */
304*ba447018SVictor Perevertkin     ExFreePoolWithTag(GuidString.Buffer, 0);
305*ba447018SVictor Perevertkin 
306*ba447018SVictor Perevertkin     /* Write the entry */
307*ba447018SVictor Perevertkin     RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
308*ba447018SVictor Perevertkin                           DatabasePath,
309*ba447018SVictor Perevertkin                           String,
310*ba447018SVictor Perevertkin                           REG_BINARY,
311*ba447018SVictor Perevertkin                           UniqueId->UniqueId,
312*ba447018SVictor Perevertkin                           UniqueId->UniqueIdLength);
313*ba447018SVictor Perevertkin 
314*ba447018SVictor Perevertkin     FreePool(String);
315*ba447018SVictor Perevertkin 
316*ba447018SVictor Perevertkin     return;
317*ba447018SVictor Perevertkin }
318*ba447018SVictor Perevertkin 
319*ba447018SVictor Perevertkin /*
320*ba447018SVictor Perevertkin  * @implemented
321*ba447018SVictor Perevertkin  */
322*ba447018SVictor Perevertkin NTSTATUS
323*ba447018SVictor Perevertkin NTAPI
CheckForNoDriveLetterEntry(IN PWSTR ValueName,IN ULONG ValueType,IN PVOID ValueData,IN ULONG ValueLength,IN PVOID Context,IN PVOID EntryContext)324*ba447018SVictor Perevertkin CheckForNoDriveLetterEntry(IN PWSTR ValueName,
325*ba447018SVictor Perevertkin                            IN ULONG ValueType,
326*ba447018SVictor Perevertkin                            IN PVOID ValueData,
327*ba447018SVictor Perevertkin                            IN ULONG ValueLength,
328*ba447018SVictor Perevertkin                            IN PVOID Context,
329*ba447018SVictor Perevertkin                            IN PVOID EntryContext)
330*ba447018SVictor Perevertkin {
331*ba447018SVictor Perevertkin     PBOOLEAN EntryPresent = EntryContext;
332*ba447018SVictor Perevertkin     PMOUNTDEV_UNIQUE_ID UniqueId = Context;
333*ba447018SVictor Perevertkin 
334*ba447018SVictor Perevertkin     /* Check if matches no drive letter entry */
335*ba447018SVictor Perevertkin     if (ValueName[0] != L'#' || ValueType != REG_BINARY ||
336*ba447018SVictor Perevertkin         UniqueId->UniqueIdLength != ValueLength)
337*ba447018SVictor Perevertkin     {
338*ba447018SVictor Perevertkin         return STATUS_SUCCESS;
339*ba447018SVictor Perevertkin     }
340*ba447018SVictor Perevertkin 
341*ba447018SVictor Perevertkin     /* Compare unique ID */
342*ba447018SVictor Perevertkin     if (RtlCompareMemory(UniqueId->UniqueId, ValueData, ValueLength) == ValueLength)
343*ba447018SVictor Perevertkin     {
344*ba447018SVictor Perevertkin         *EntryPresent = TRUE;
345*ba447018SVictor Perevertkin     }
346*ba447018SVictor Perevertkin 
347*ba447018SVictor Perevertkin     return STATUS_SUCCESS;
348*ba447018SVictor Perevertkin }
349*ba447018SVictor Perevertkin 
350*ba447018SVictor Perevertkin /*
351*ba447018SVictor Perevertkin  * @implemented
352*ba447018SVictor Perevertkin  */
353*ba447018SVictor Perevertkin BOOLEAN
HasNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)354*ba447018SVictor Perevertkin HasNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
355*ba447018SVictor Perevertkin {
356*ba447018SVictor Perevertkin     BOOLEAN EntryPresent = FALSE;
357*ba447018SVictor Perevertkin     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
358*ba447018SVictor Perevertkin 
359*ba447018SVictor Perevertkin     RtlZeroMemory(QueryTable, sizeof(QueryTable));
360*ba447018SVictor Perevertkin     QueryTable[0].QueryRoutine = CheckForNoDriveLetterEntry;
361*ba447018SVictor Perevertkin     QueryTable[0].EntryContext = &EntryPresent;
362*ba447018SVictor Perevertkin 
363*ba447018SVictor Perevertkin     RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
364*ba447018SVictor Perevertkin                            DatabasePath,
365*ba447018SVictor Perevertkin                            QueryTable,
366*ba447018SVictor Perevertkin                            UniqueId,
367*ba447018SVictor Perevertkin                            NULL);
368*ba447018SVictor Perevertkin 
369*ba447018SVictor Perevertkin     return EntryPresent;
370*ba447018SVictor Perevertkin }
371*ba447018SVictor Perevertkin 
372*ba447018SVictor Perevertkin /*
373*ba447018SVictor Perevertkin  * @implemented
374*ba447018SVictor Perevertkin  */
375*ba447018SVictor Perevertkin VOID
UpdateReplicatedUniqueIds(IN PDEVICE_INFORMATION DeviceInformation,IN PDATABASE_ENTRY DatabaseEntry)376*ba447018SVictor Perevertkin UpdateReplicatedUniqueIds(IN PDEVICE_INFORMATION DeviceInformation, IN PDATABASE_ENTRY DatabaseEntry)
377*ba447018SVictor Perevertkin {
378*ba447018SVictor Perevertkin     PLIST_ENTRY NextEntry;
379*ba447018SVictor Perevertkin     PUNIQUE_ID_REPLICATE ReplicatedUniqueId, NewEntry;
380*ba447018SVictor Perevertkin 
381*ba447018SVictor Perevertkin     /* Browse all the device replicated unique IDs */
382*ba447018SVictor Perevertkin     for (NextEntry = DeviceInformation->ReplicatedUniqueIdsListHead.Flink;
383*ba447018SVictor Perevertkin          NextEntry != &(DeviceInformation->ReplicatedUniqueIdsListHead);
384*ba447018SVictor Perevertkin          NextEntry = NextEntry->Flink)
385*ba447018SVictor Perevertkin     {
386*ba447018SVictor Perevertkin         ReplicatedUniqueId = CONTAINING_RECORD(NextEntry,
387*ba447018SVictor Perevertkin                                                UNIQUE_ID_REPLICATE,
388*ba447018SVictor Perevertkin                                                ReplicatedUniqueIdsListEntry);
389*ba447018SVictor Perevertkin 
390*ba447018SVictor Perevertkin         if (ReplicatedUniqueId->UniqueId->UniqueIdLength != DatabaseEntry->UniqueIdLength)
391*ba447018SVictor Perevertkin         {
392*ba447018SVictor Perevertkin             continue;
393*ba447018SVictor Perevertkin         }
394*ba447018SVictor Perevertkin 
395*ba447018SVictor Perevertkin         /* If we find the UniqueId to update, break */
396*ba447018SVictor Perevertkin         if (RtlCompareMemory(ReplicatedUniqueId->UniqueId->UniqueId,
397*ba447018SVictor Perevertkin                              (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
398*ba447018SVictor Perevertkin                              ReplicatedUniqueId->UniqueId->UniqueIdLength) == ReplicatedUniqueId->UniqueId->UniqueIdLength)
399*ba447018SVictor Perevertkin         {
400*ba447018SVictor Perevertkin             break;
401*ba447018SVictor Perevertkin         }
402*ba447018SVictor Perevertkin     }
403*ba447018SVictor Perevertkin 
404*ba447018SVictor Perevertkin     /* We found the unique ID, no need to continue */
405*ba447018SVictor Perevertkin     if (NextEntry != &(DeviceInformation->ReplicatedUniqueIdsListHead))
406*ba447018SVictor Perevertkin     {
407*ba447018SVictor Perevertkin         return;
408*ba447018SVictor Perevertkin     }
409*ba447018SVictor Perevertkin 
410*ba447018SVictor Perevertkin     /* Allocate a new entry for unique ID */
411*ba447018SVictor Perevertkin     NewEntry = AllocatePool(sizeof(UNIQUE_ID_REPLICATE));
412*ba447018SVictor Perevertkin     if (!NewEntry)
413*ba447018SVictor Perevertkin     {
414*ba447018SVictor Perevertkin         return;
415*ba447018SVictor Perevertkin     }
416*ba447018SVictor Perevertkin 
417*ba447018SVictor Perevertkin     /* Allocate the unique ID */
418*ba447018SVictor Perevertkin     NewEntry->UniqueId = AllocatePool(DatabaseEntry->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
419*ba447018SVictor Perevertkin     if (!NewEntry->UniqueId)
420*ba447018SVictor Perevertkin     {
421*ba447018SVictor Perevertkin         FreePool(NewEntry);
422*ba447018SVictor Perevertkin         return;
423*ba447018SVictor Perevertkin     }
424*ba447018SVictor Perevertkin 
425*ba447018SVictor Perevertkin     /* Copy */
426*ba447018SVictor Perevertkin     NewEntry->UniqueId->UniqueIdLength = DatabaseEntry->UniqueIdLength;
427*ba447018SVictor Perevertkin     RtlCopyMemory(NewEntry->UniqueId->UniqueId,
428*ba447018SVictor Perevertkin                   (PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
429*ba447018SVictor Perevertkin                   DatabaseEntry->UniqueIdLength);
430*ba447018SVictor Perevertkin     /* And insert into replicated unique IDs list */
431*ba447018SVictor Perevertkin     InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &NewEntry->ReplicatedUniqueIdsListEntry);
432*ba447018SVictor Perevertkin 
433*ba447018SVictor Perevertkin     return;
434*ba447018SVictor Perevertkin }
435