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