[NTOSKRNL] De-duplicate code between Ob(f)DereferenceDeviceMap functions
[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 ObDereferenceObject(DeviceMap->DosDevicesDirectory );
193 ExFreePoolWithTag(DeviceMap, 'mDbO');
194 }
195
196
197 VOID
198 NTAPI
199 ObInheritDeviceMap(IN PEPROCESS Parent,
200 IN PEPROCESS Process)
201 {
202 PDEVICE_MAP DeviceMap;
203
204 DPRINT("ObInheritDeviceMap()\n");
205
206 /* Acquire the device map lock */
207 KeAcquireGuardedMutex(&ObpDeviceMapLock);
208
209 /* Get the parent process device map or the system device map */
210 DeviceMap = (Parent != NULL) ? Parent->DeviceMap : ObSystemDeviceMap;
211 if (DeviceMap != NULL)
212 {
213 /* Reference the device map and attach it to the new process */
214 DeviceMap->ReferenceCount++;
215 DPRINT("ReferenceCount: %lu\n", DeviceMap->ReferenceCount);
216
217 Process->DeviceMap = DeviceMap;
218 }
219
220 /* Release the device map lock */
221 KeReleaseGuardedMutex(&ObpDeviceMapLock);
222 }
223
224
225 VOID
226 NTAPI
227 ObQueryDeviceMapInformation(IN PEPROCESS Process,
228 IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
229 {
230 PDEVICE_MAP DeviceMap;
231
232 /* Acquire the device map lock */
233 KeAcquireGuardedMutex(&ObpDeviceMapLock);
234
235 /* Get the process device map or the system device map */
236 DeviceMap = (Process != NULL) ? Process->DeviceMap : ObSystemDeviceMap;
237 if (DeviceMap != NULL)
238 {
239 /* Make a copy */
240 DeviceMapInfo->Query.DriveMap = DeviceMap->DriveMap;
241 RtlCopyMemory(DeviceMapInfo->Query.DriveType,
242 DeviceMap->DriveType,
243 sizeof(DeviceMap->DriveType));
244 }
245
246 /* Release the device map lock */
247 KeReleaseGuardedMutex(&ObpDeviceMapLock);
248 }
249
250
251 #if 0
252 NTSTATUS
253 NTAPI
254 ObIsDosDeviceLocallyMapped(
255 IN ULONG Index,
256 OUT PUCHAR DosDeviceState)
257 {
258 /* Check the index */
259 if (Index < 1 || Index > 26)
260 return STATUS_INVALID_PARAMETER;
261
262 /* Acquire the device map lock */
263 KeAcquireGuardedMutex(&ObpDeviceMapLock);
264
265 /* Get drive mapping status */
266 *DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0;
267
268 /* Release the device map lock */
269 KeReleaseGuardedMutex(&ObpDeviceMapLock);
270
271 return STATUS_SUCCESS;
272 }
273 #endif
274
275 /* EOF */