c79838bbabdea81c4e83636e187a18f8390047ae
[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 return;
161
162 /* Acquire the device map lock again */
163 KeAcquireGuardedMutex(&ObpDeviceMapLock);
164
165 /* Decrement the reference counter */
166 DeviceMap->ReferenceCount--;
167 DPRINT("ReferenceCount: %lu\n", DeviceMap->ReferenceCount);
168
169 /* Leave, if there are still references to this device map */
170 if (DeviceMap->ReferenceCount != 0)
171 {
172 /* Release the device map lock and leave */
173 KeReleaseGuardedMutex(&ObpDeviceMapLock);
174 return;
175 }
176
177 /* Nobody is referencing it anymore, unlink the DOS directory */
178 DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
179
180 /* Release the device map lock */
181 KeReleaseGuardedMutex(&ObpDeviceMapLock);
182
183 /* Dereference the DOS Devices Directory and free the DeviceMap */
184 ObDereferenceObject(DeviceMap->DosDevicesDirectory);
185 ExFreePoolWithTag(DeviceMap, 'mDbO');
186 }
187
188
189 VOID
190 FASTCALL
191 ObfDereferenceDeviceMap(IN PDEVICE_MAP DeviceMap)
192 {
193 DPRINT("ObfDereferenceDeviceMap()\n");
194
195 /* Acquire the device map lock */
196 KeAcquireGuardedMutex(&ObpDeviceMapLock);
197
198 /* Decrement the reference counter */
199 DeviceMap->ReferenceCount--;
200 DPRINT("ReferenceCount: %lu\n", DeviceMap->ReferenceCount);
201
202 /* Leave, if there are still references to this device map */
203 if (DeviceMap->ReferenceCount != 0)
204 {
205 /* Release the device map lock and leave */
206 KeReleaseGuardedMutex(&ObpDeviceMapLock);
207 return;
208 }
209
210 /* Nobody is referencing it anymore, unlink the DOS directory */
211 DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
212
213 /* Release the devicemap lock */
214 KeReleaseGuardedMutex(&ObpDeviceMapLock);
215
216 /* Dereference the DOS Devices Directory and free the Device Map */
217 ObDereferenceObject(DeviceMap->DosDevicesDirectory );
218 ExFreePoolWithTag(DeviceMap, 'mDbO');
219 }
220
221
222 VOID
223 NTAPI
224 ObInheritDeviceMap(IN PEPROCESS Parent,
225 IN PEPROCESS Process)
226 {
227 PDEVICE_MAP DeviceMap;
228
229 DPRINT("ObInheritDeviceMap()\n");
230
231 /* Acquire the device map lock */
232 KeAcquireGuardedMutex(&ObpDeviceMapLock);
233
234 /* Get the parent process device map or the system device map */
235 DeviceMap = (Parent != NULL) ? Parent->DeviceMap : ObSystemDeviceMap;
236 if (DeviceMap != NULL)
237 {
238 /* Reference the device map and attach it to the new process */
239 DeviceMap->ReferenceCount++;
240 DPRINT("ReferenceCount: %lu\n", DeviceMap->ReferenceCount);
241
242 Process->DeviceMap = DeviceMap;
243 }
244
245 /* Release the device map lock */
246 KeReleaseGuardedMutex(&ObpDeviceMapLock);
247 }
248
249
250 VOID
251 NTAPI
252 ObQueryDeviceMapInformation(IN PEPROCESS Process,
253 IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
254 {
255 PDEVICE_MAP DeviceMap;
256
257 /* Acquire the device map lock */
258 KeAcquireGuardedMutex(&ObpDeviceMapLock);
259
260 /* Get the process device map or the system device map */
261 DeviceMap = (Process != NULL) ? Process->DeviceMap : ObSystemDeviceMap;
262 if (DeviceMap != NULL)
263 {
264 /* Make a copy */
265 DeviceMapInfo->Query.DriveMap = DeviceMap->DriveMap;
266 RtlCopyMemory(DeviceMapInfo->Query.DriveType,
267 DeviceMap->DriveType,
268 sizeof(DeviceMap->DriveType));
269 }
270
271 /* Release the device map lock */
272 KeReleaseGuardedMutex(&ObpDeviceMapLock);
273 }
274
275
276 #if 0
277 NTSTATUS
278 NTAPI
279 ObIsDosDeviceLocallyMapped(
280 IN ULONG Index,
281 OUT PUCHAR DosDeviceState)
282 {
283 /* Check the index */
284 if (Index < 1 || Index > 26)
285 return STATUS_INVALID_PARAMETER;
286
287 /* Acquire the device map lock */
288 KeAcquireGuardedMutex(&ObpDeviceMapLock);
289
290 /* Get drive mapping status */
291 *DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0;
292
293 /* Release the device map lock */
294 KeReleaseGuardedMutex(&ObpDeviceMapLock);
295
296 return STATUS_SUCCESS;
297 }
298 #endif
299
300 /* EOF */