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)
10 /* INCLUDES ***************************************************************/
16 ULONG ObpLUIDDeviceMapsDisabled
;
17 ULONG ObpLUIDDeviceMapsEnabled
;
19 /* PRIVATE FUNCTIONS ******************************************************/
23 ObSetDeviceMap(IN PEPROCESS Process
,
24 IN HANDLE DirectoryHandle
)
26 POBJECT_DIRECTORY DirectoryObject
= NULL
;
27 PDEVICE_MAP DeviceMap
= NULL
, NewDeviceMap
= NULL
, OldDeviceMap
;
29 PEPROCESS WorkProcess
;
30 BOOLEAN MakePermanant
= FALSE
;
32 Status
= ObReferenceObjectByHandle(DirectoryHandle
,
34 ObpDirectoryObjectType
,
36 (PVOID
*)&DirectoryObject
,
38 if (!NT_SUCCESS(Status
))
40 DPRINT("ObReferenceObjectByHandle() failed (Status 0x%08lx)\n", Status
);
44 /* Allocate and initialize a new device map */
45 DeviceMap
= ExAllocatePoolWithTag(PagedPool
,
48 if (DeviceMap
== NULL
)
50 ObDereferenceObject(DirectoryObject
);
51 return STATUS_INSUFFICIENT_RESOURCES
;
54 /* Initialize the device map */
55 RtlZeroMemory(DeviceMap
, sizeof(*DeviceMap
));
56 DeviceMap
->ReferenceCount
= 1;
57 DeviceMap
->DosDevicesDirectory
= DirectoryObject
;
59 /* Acquire the device map lock */
60 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
62 /* Attach the device map to the directory object */
63 if (DirectoryObject
->DeviceMap
== NULL
)
65 DirectoryObject
->DeviceMap
= DeviceMap
;
69 NewDeviceMap
= DeviceMap
;
71 /* There's already a device map,
73 DeviceMap
= DirectoryObject
->DeviceMap
;
74 ++DeviceMap
->ReferenceCount
;
77 /* Caller gave a process, use it */
80 WorkProcess
= Process
;
82 /* If no process given, use current and
83 * set system device map */
86 WorkProcess
= PsGetCurrentProcess();
87 ObSystemDeviceMap
= DeviceMap
;
90 /* If current object isn't system one, save system one in current
92 if (DirectoryObject
!= ObSystemDeviceMap
->DosDevicesDirectory
)
94 /* We also need to make the object permanant */
95 DeviceMap
->GlobalDosDevicesDirectory
= ObSystemDeviceMap
->DosDevicesDirectory
;
99 /* Save old process device map */
100 OldDeviceMap
= WorkProcess
->DeviceMap
;
101 /* Attach the device map to the process */
102 WorkProcess
->DeviceMap
= DeviceMap
;
104 /* Release the device map lock */
105 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
107 /* If we have to make the object permamant, do it now */
110 POBJECT_HEADER ObjectHeader
;
111 POBJECT_HEADER_NAME_INFO HeaderNameInfo
;
113 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(DirectoryObject
);
114 HeaderNameInfo
= ObpReferenceNameInfo(ObjectHeader
);
116 ObpEnterObjectTypeMutex(ObjectHeader
->Type
);
117 if (HeaderNameInfo
!= NULL
&& HeaderNameInfo
->Directory
!= NULL
)
119 ObjectHeader
->Flags
|= OB_FLAG_PERMANENT
;
121 ObpLeaveObjectTypeMutex(ObjectHeader
->Type
);
123 if (HeaderNameInfo
!= NULL
)
125 ObpDereferenceNameInfo(HeaderNameInfo
);
129 /* Release useless device map if required */
130 if (NewDeviceMap
!= NULL
)
132 ObfDereferenceObject(DirectoryObject
);
133 ExFreePoolWithTag(NewDeviceMap
, 'mDbO');
136 /* And dereference previous process device map */
137 if (OldDeviceMap
!= NULL
)
139 ObfDereferenceDeviceMap(OldDeviceMap
);
142 return STATUS_SUCCESS
;
148 ObpSetCurrentProcessDeviceMap(VOID
)
150 return STATUS_NOT_IMPLEMENTED
;
156 ObpReferenceDeviceMap(VOID
)
161 PDEVICE_MAP DeviceMap
;
162 PETHREAD CurrentThread
;
163 BOOLEAN LookingForSystem
;
164 LUID SystemLuid
= SYSTEM_LUID
;
165 BOOLEAN CopyOnOpen
, EffectiveOnly
;
166 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
168 LookingForSystem
= FALSE
;
170 /* If LUID mapping is enable, try to get appropriate device map */
171 if (ObpLUIDDeviceMapsEnabled
!= 0)
173 /* In case of impersonation, we've got a bit of work to do */
174 CurrentThread
= PsGetCurrentThread();
175 if (CurrentThread
->ActiveImpersonationInfo
)
177 /* Get impersonation token */
178 Token
= PsReferenceImpersonationToken(CurrentThread
,
181 &ImpersonationLevel
);
185 Status
= SeQueryAuthenticationIdToken(Token
, &LogonId
);
190 Status
= STATUS_NO_TOKEN
;
193 /* If we got logon LUID */
194 if (NT_SUCCESS(Status
))
197 * Check it's not system, system is easy to handle,
198 * we just need to return ObSystemDeviceMap
200 if (!RtlEqualLuid(&LogonId
, &SystemLuid
))
202 /* Ask Se for the device map */
203 Status
= SeGetLogonIdDeviceMap(&LogonId
, &DeviceMap
);
204 if (NT_SUCCESS(Status
))
206 /* Acquire the device map lock */
207 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
209 /* Reference the device map if any */
210 if (DeviceMap
!= NULL
)
212 ++DeviceMap
->ReferenceCount
;
215 /* Release the device map lock */
216 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
218 /* If we got the device map, we're done! */
219 if (DeviceMap
!= NULL
)
221 ObDereferenceObject(Token
);
229 LookingForSystem
= TRUE
;
235 * Fall back case of the LUID mapping, make sure there's a
236 * a device map attached to the current process
238 if (PsGetCurrentProcess()->DeviceMap
== NULL
&&
239 !NT_SUCCESS(ObpSetCurrentProcessDeviceMap()))
241 /* We may have failed after we got impersonation token */
244 ObDereferenceObject(Token
);
251 /* Acquire the device map lock */
252 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
254 /* If we're looking for system map, use it */
255 if (LookingForSystem
)
257 DeviceMap
= ObSystemDeviceMap
;
259 /* Otherwise, use current process device map */
262 DeviceMap
= PsGetCurrentProcess()->DeviceMap
;
265 /* If we got one, reference it */
266 if (DeviceMap
!= NULL
)
268 ++DeviceMap
->ReferenceCount
;
271 /* Release the device map lock */
272 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
274 /* We may have impersonation token (if we failed in impersonation branch) */
277 ObDereferenceObject(Token
);
280 /* Return the potentially found device map */
287 ObDereferenceDeviceMap(IN PEPROCESS Process
)
289 PDEVICE_MAP DeviceMap
;
291 DPRINT("ObDereferenceDeviceMap()\n");
293 /* Get the pointer to this process devicemap and reset it
294 holding the device map lock */
295 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
296 DeviceMap
= Process
->DeviceMap
;
297 Process
->DeviceMap
= NULL
;
298 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
300 /* Continue only if there is a device map */
301 if (DeviceMap
!= NULL
)
302 ObfDereferenceDeviceMap(DeviceMap
);
308 ObfDereferenceDeviceMap(IN PDEVICE_MAP DeviceMap
)
310 DPRINT("ObfDereferenceDeviceMap()\n");
312 /* Acquire the device map lock */
313 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
315 /* Decrement the reference counter */
316 DeviceMap
->ReferenceCount
--;
317 DPRINT("ReferenceCount: %lu\n", DeviceMap
->ReferenceCount
);
319 /* Leave, if there are still references to this device map */
320 if (DeviceMap
->ReferenceCount
!= 0)
322 /* Release the device map lock and leave */
323 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
327 /* Nobody is referencing it anymore, unlink the DOS directory */
328 DeviceMap
->DosDevicesDirectory
->DeviceMap
= NULL
;
330 /* Release the devicemap lock */
331 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
333 /* Dereference the DOS Devices Directory and free the Device Map */
334 ObMakeTemporaryObject(DeviceMap
->DosDevicesDirectory
);
335 ObDereferenceObject(DeviceMap
->DosDevicesDirectory
);
336 ExFreePoolWithTag(DeviceMap
, 'mDbO');
342 ObInheritDeviceMap(IN PEPROCESS Parent
,
343 IN PEPROCESS Process
)
345 PDEVICE_MAP DeviceMap
;
347 DPRINT("ObInheritDeviceMap()\n");
349 /* Acquire the device map lock */
350 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
352 /* Get the parent process device map or the system device map */
353 DeviceMap
= (Parent
!= NULL
) ? Parent
->DeviceMap
: ObSystemDeviceMap
;
354 if (DeviceMap
!= NULL
)
356 /* Reference the device map and attach it to the new process */
357 DeviceMap
->ReferenceCount
++;
358 DPRINT("ReferenceCount: %lu\n", DeviceMap
->ReferenceCount
);
360 Process
->DeviceMap
= DeviceMap
;
363 /* Release the device map lock */
364 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
370 ObQueryDeviceMapInformation(IN PEPROCESS Process
,
371 IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo
,
374 PDEVICE_MAP DeviceMap
= NULL
, GlobalDeviceMap
;
376 PROCESS_DEVICEMAP_INFORMATION MapInfo
;
382 if (Flags
& ~PROCESS_LUID_DOSDEVICES_ONLY
)
384 return STATUS_INVALID_PARAMETER
;
388 /* Do we want to return anything? */
389 ReturnAny
= ~Flags
& PROCESS_LUID_DOSDEVICES_ONLY
;
391 /* If LUID mappings are enabled... */
392 if (ObpLUIDDeviceMapsEnabled
!= 0)
394 /* Check for process parameter validness */
395 if (Process
!= NULL
&& Process
!= PsGetCurrentProcess())
397 return STATUS_INVALID_PARAMETER
;
400 /* And get the device map */
401 DeviceMap
= ObpReferenceDeviceMap();
404 /* Acquire the device map lock */
405 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
408 * If we had a device map, if because of LUID mappings,
409 * we'll have to dereference it afterwards
411 if (DeviceMap
!= NULL
)
417 /* Get the process device map or the system device map */
418 DeviceMap
= (Process
!= NULL
) ? Process
->DeviceMap
: ObSystemDeviceMap
;
421 /* Fail if no device map */
422 if (DeviceMap
== NULL
)
424 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
425 return STATUS_END_OF_FILE
;
428 /* At that point, assume success */
429 Status
= STATUS_SUCCESS
;
431 /* Try to get the global device map if any */
432 GlobalDeviceMap
= DeviceMap
;
433 if (DeviceMap
->GlobalDosDevicesDirectory
!= NULL
)
435 if (DeviceMap
->GlobalDosDevicesDirectory
->DeviceMap
!= NULL
)
437 GlobalDeviceMap
= DeviceMap
->GlobalDosDevicesDirectory
->DeviceMap
;
441 /* Now, setup our device map info, especially drive types */
442 MapInfo
.Query
.DriveMap
= DeviceMap
->DriveMap
;
443 /* Browse every device */
444 for (i
= 0, BitMask
= 1; i
< 32; ++i
, BitMask
*= 2)
446 /* Set the type given current device map */
447 MapInfo
.Query
.DriveType
[i
] = DeviceMap
->DriveType
[i
];
450 * If device is not existing and we're asked to return
451 * more than just LUID mapped, get the entry
452 * from global device map if not remote
454 if (!(MapInfo
.Query
.DriveMap
& BitMask
) && ReturnAny
)
456 if (ObpLUIDDeviceMapsEnabled
!= 0 ||
457 (GlobalDeviceMap
->DriveType
[i
] != DOSDEVICE_DRIVE_REMOTE
&&
458 GlobalDeviceMap
->DriveType
[i
] != DOSDEVICE_DRIVE_CALCULATE
))
460 MapInfo
.Query
.DriveType
[i
] = GlobalDeviceMap
->DriveType
[i
];
461 MapInfo
.Query
.DriveMap
|= BitMask
& GlobalDeviceMap
->DriveMap
;
466 /* Release the device map lock */
467 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
469 /* Dereference LUID device map */
472 ObfDereferenceDeviceMap(DeviceMap
);
478 RtlCopyMemory(DeviceMapInfo
, &MapInfo
, sizeof(PROCESS_DEVICEMAP_INFORMATION
));
480 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
482 Status
= _SEH2_GetExceptionCode();
492 ObIsLUIDDeviceMapsEnabled(VOID
)
494 return ObpLUIDDeviceMapsEnabled
;
501 ObIsDosDeviceLocallyMapped(
503 OUT PUCHAR DosDeviceState
)
505 /* Check the index */
506 if (Index
< 1 || Index
> 26)
507 return STATUS_INVALID_PARAMETER
;
509 /* Acquire the device map lock */
510 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
512 /* Get drive mapping status */
513 *DosDeviceState
= (ObSystemDeviceMap
->DriveMap
& (1 << Index
)) != 0;
515 /* Release the device map lock */
516 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
518 return STATUS_SUCCESS
;