[NTOSKRNL] On device map freeing, make directory object temporary again
[reactos.git] / ntoskrnl / ob / devicemap.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ob/devicemap.c
5 * PURPOSE: Device map implementation
6 * PROGRAMMERS: Eric Kohl (eric.kohl@reactos.org)
7 * Alex Ionescu (alex.ionescu@reactos.org)
8 */
9
10 /* INCLUDES ***************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* PRIVATE FUNCTIONS ******************************************************/
17
18 NTSTATUS
19 NTAPI
20 ObSetDeviceMap(IN PEPROCESS Process,
21 IN HANDLE DirectoryHandle)
22 {
23 POBJECT_DIRECTORY DirectoryObject = NULL;
24 PDEVICE_MAP DeviceMap = NULL, NewDeviceMap = NULL, OldDeviceMap;
25 NTSTATUS Status;
26 PEPROCESS WorkProcess;
27 BOOLEAN MakePermanant = FALSE;
28
29 Status = ObReferenceObjectByHandle(DirectoryHandle,
30 DIRECTORY_TRAVERSE,
31 ObpDirectoryObjectType,
32 KeGetPreviousMode(),
33 (PVOID*)&DirectoryObject,
34 NULL);
35 if (!NT_SUCCESS(Status))
36 {
37 DPRINT("ObReferenceObjectByHandle() failed (Status 0x%08lx)\n", Status);
38 return Status;
39 }
40
41 /* Allocate and initialize a new device map */
42 DeviceMap = ExAllocatePoolWithTag(PagedPool,
43 sizeof(*DeviceMap),
44 'mDbO');
45 if (DeviceMap == NULL)
46 {
47 ObDereferenceObject(DirectoryObject);
48 return STATUS_INSUFFICIENT_RESOURCES;
49 }
50
51 /* Initialize the device map */
52 RtlZeroMemory(DeviceMap, sizeof(*DeviceMap));
53 DeviceMap->ReferenceCount = 1;
54 DeviceMap->DosDevicesDirectory = DirectoryObject;
55
56 /* Acquire the device map lock */
57 KeAcquireGuardedMutex(&ObpDeviceMapLock);
58
59 /* Attach the device map to the directory object */
60 if (DirectoryObject->DeviceMap == NULL)
61 {
62 DirectoryObject->DeviceMap = DeviceMap;
63 }
64 else
65 {
66 NewDeviceMap = DeviceMap;
67
68 /* There's already a device map,
69 so reuse it */
70 DeviceMap = DirectoryObject->DeviceMap;
71 ++DeviceMap->ReferenceCount;
72 }
73
74 /* Caller gave a process, use it */
75 if (Process != NULL)
76 {
77 WorkProcess = Process;
78 }
79 /* If no process given, use current and
80 * set system device map */
81 else
82 {
83 WorkProcess = PsGetCurrentProcess();
84 ObSystemDeviceMap = DeviceMap;
85 }
86
87 /* If current object isn't system one, save system one in current
88 * device map */
89 if (DirectoryObject != ObSystemDeviceMap->DosDevicesDirectory)
90 {
91 /* We also need to make the object permanant */
92 DeviceMap->GlobalDosDevicesDirectory = ObSystemDeviceMap->DosDevicesDirectory;
93 MakePermanant = TRUE;
94 }
95
96 /* Save old process device map */
97 OldDeviceMap = WorkProcess->DeviceMap;
98 /* Attach the device map to the process */
99 WorkProcess->DeviceMap = DeviceMap;
100
101 /* Release the device map lock */
102 KeReleaseGuardedMutex(&ObpDeviceMapLock);
103
104 /* If we have to make the object permamant, do it now */
105 if (MakePermanant)
106 {
107 POBJECT_HEADER ObjectHeader;
108 POBJECT_HEADER_NAME_INFO HeaderNameInfo;
109
110 ObjectHeader = OBJECT_TO_OBJECT_HEADER(DirectoryObject);
111 HeaderNameInfo = ObpReferenceNameInfo(ObjectHeader);
112
113 ObpEnterObjectTypeMutex(ObjectHeader->Type);
114 if (HeaderNameInfo != NULL && HeaderNameInfo->Directory != NULL)
115 {
116 ObjectHeader->Flags |= OB_FLAG_PERMANENT;
117 }
118 ObpLeaveObjectTypeMutex(ObjectHeader->Type);
119
120 if (HeaderNameInfo != NULL)
121 {
122 ObpDereferenceNameInfo(HeaderNameInfo);
123 }
124 }
125
126 /* Release useless device map if required */
127 if (NewDeviceMap != NULL)
128 {
129 ObfDereferenceObject(DirectoryObject);
130 ExFreePoolWithTag(NewDeviceMap, 'mDbO');
131 }
132
133 /* And dereference previous process device map */
134 if (OldDeviceMap != NULL)
135 {
136 ObfDereferenceDeviceMap(OldDeviceMap);
137 }
138
139 return STATUS_SUCCESS;
140 }
141
142
143 VOID
144 NTAPI
145 ObDereferenceDeviceMap(IN PEPROCESS Process)
146 {
147 PDEVICE_MAP DeviceMap;
148
149 DPRINT("ObDereferenceDeviceMap()\n");
150
151 /* Get the pointer to this process devicemap and reset it
152 holding the device map lock */
153 KeAcquireGuardedMutex(&ObpDeviceMapLock);
154 DeviceMap = Process->DeviceMap;
155 Process->DeviceMap = NULL;
156 KeReleaseGuardedMutex(&ObpDeviceMapLock);
157
158 /* Continue only if there is a device map */
159 if (DeviceMap != NULL)
160 ObfDereferenceDeviceMap(DeviceMap);
161 }
162
163
164 VOID
165 FASTCALL
166 ObfDereferenceDeviceMap(IN PDEVICE_MAP DeviceMap)
167 {
168 DPRINT("ObfDereferenceDeviceMap()\n");
169
170 /* Acquire the device map lock */
171 KeAcquireGuardedMutex(&ObpDeviceMapLock);
172
173 /* Decrement the reference counter */
174 DeviceMap->ReferenceCount--;
175 DPRINT("ReferenceCount: %lu\n", DeviceMap->ReferenceCount);
176
177 /* Leave, if there are still references to this device map */
178 if (DeviceMap->ReferenceCount != 0)
179 {
180 /* Release the device map lock and leave */
181 KeReleaseGuardedMutex(&ObpDeviceMapLock);
182 return;
183 }
184
185 /* Nobody is referencing it anymore, unlink the DOS directory */
186 DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
187
188 /* Release the devicemap lock */
189 KeReleaseGuardedMutex(&ObpDeviceMapLock);
190
191 /* Dereference the DOS Devices Directory and free the Device Map */
192 ObMakeTemporaryObject(DeviceMap->DosDevicesDirectory);
193 ObDereferenceObject(DeviceMap->DosDevicesDirectory);
194 ExFreePoolWithTag(DeviceMap, 'mDbO');
195 }
196
197
198 VOID
199 NTAPI
200 ObInheritDeviceMap(IN PEPROCESS Parent,
201 IN PEPROCESS Process)
202 {
203 PDEVICE_MAP DeviceMap;
204
205 DPRINT("ObInheritDeviceMap()\n");
206
207 /* Acquire the device map lock */
208 KeAcquireGuardedMutex(&ObpDeviceMapLock);
209
210 /* Get the parent process device map or the system device map */
211 DeviceMap = (Parent != NULL) ? Parent->DeviceMap : ObSystemDeviceMap;
212 if (DeviceMap != NULL)
213 {
214 /* Reference the device map and attach it to the new process */
215 DeviceMap->ReferenceCount++;
216 DPRINT("ReferenceCount: %lu\n", DeviceMap->ReferenceCount);
217
218 Process->DeviceMap = DeviceMap;
219 }
220
221 /* Release the device map lock */
222 KeReleaseGuardedMutex(&ObpDeviceMapLock);
223 }
224
225
226 VOID
227 NTAPI
228 ObQueryDeviceMapInformation(IN PEPROCESS Process,
229 IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
230 {
231 PDEVICE_MAP DeviceMap;
232
233 /* Acquire the device map lock */
234 KeAcquireGuardedMutex(&ObpDeviceMapLock);
235
236 /* Get the process device map or the system device map */
237 DeviceMap = (Process != NULL) ? Process->DeviceMap : ObSystemDeviceMap;
238 if (DeviceMap != NULL)
239 {
240 /* Make a copy */
241 DeviceMapInfo->Query.DriveMap = DeviceMap->DriveMap;
242 RtlCopyMemory(DeviceMapInfo->Query.DriveType,
243 DeviceMap->DriveType,
244 sizeof(DeviceMap->DriveType));
245 }
246
247 /* Release the device map lock */
248 KeReleaseGuardedMutex(&ObpDeviceMapLock);
249 }
250
251
252 #if 0
253 NTSTATUS
254 NTAPI
255 ObIsDosDeviceLocallyMapped(
256 IN ULONG Index,
257 OUT PUCHAR DosDeviceState)
258 {
259 /* Check the index */
260 if (Index < 1 || Index > 26)
261 return STATUS_INVALID_PARAMETER;
262
263 /* Acquire the device map lock */
264 KeAcquireGuardedMutex(&ObpDeviceMapLock);
265
266 /* Get drive mapping status */
267 *DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0;
268
269 /* Release the device map lock */
270 KeReleaseGuardedMutex(&ObpDeviceMapLock);
271
272 return STATUS_SUCCESS;
273 }
274 #endif
275
276 /* EOF */