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