* PURPOSE: Device map implementation
* PROGRAMMERS: Eric Kohl (eric.kohl@reactos.org)
* Alex Ionescu (alex.ionescu@reactos.org)
+ * Pierre Schweitzer (pierre@reactos.org)
*/
/* INCLUDES ***************************************************************/
}
+NTSTATUS
+NTAPI
+ObpSetCurrentProcessDeviceMap(VOID)
+{
+ PTOKEN Token;
+ LUID LogonId;
+ NTSTATUS Status;
+ PEPROCESS CurrentProcess;
+ LUID SystemLuid = SYSTEM_LUID;
+ PDEVICE_MAP DeviceMap, OldDeviceMap;
+
+ /* Get our impersonation token */
+ CurrentProcess = PsGetCurrentProcess();
+ Token = PsReferencePrimaryToken(CurrentProcess);
+ if (Token == NULL)
+ {
+ return STATUS_NO_TOKEN;
+ }
+
+ /* Query the Logon ID */
+ Status = SeQueryAuthenticationIdToken(Token, &LogonId);
+ if (!NT_SUCCESS(Status))
+ {
+ goto done;
+ }
+
+ /* If that's system, then use system device map */
+ if (RtlEqualLuid(&LogonId, &SystemLuid))
+ {
+ DeviceMap = ObSystemDeviceMap;
+ }
+ /* Otherwise ask Se for the device map */
+ else
+ {
+ Status = SeGetLogonIdDeviceMap(&LogonId, &DeviceMap);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Normalize failure status */
+ Status = STATUS_OBJECT_PATH_INVALID;
+ goto done;
+ }
+ }
+
+ /* Fail if no device map */
+ if (DeviceMap == NULL)
+ {
+ Status = STATUS_OBJECT_PATH_INVALID;
+ goto done;
+ }
+
+ /* Acquire the device map lock */
+ KeAcquireGuardedMutex(&ObpDeviceMapLock);
+
+ /* Save old device map attached to the process */
+ OldDeviceMap = CurrentProcess->DeviceMap;
+
+ /* Set new device map & reference it */
+ ++DeviceMap->ReferenceCount;
+ CurrentProcess->DeviceMap = DeviceMap;
+
+ /* Release the device map lock */
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
+
+ /* If we had a device map, dereference it */
+ if (OldDeviceMap != NULL)
+ {
+ ObfDereferenceDeviceMap(OldDeviceMap);
+ }
+
+done:
+ /* We're done with the token! */
+ ObDereferenceObject(Token);
+
+ return Status;
+}
+
+
PDEVICE_MAP
NTAPI
ObpReferenceDeviceMap(VOID)
{
- UNIMPLEMENTED;
- return NULL;
+ LUID LogonId;
+ NTSTATUS Status;
+ PTOKEN Token = NULL;
+ PDEVICE_MAP DeviceMap;
+ PETHREAD CurrentThread;
+ BOOLEAN LookingForSystem;
+ LUID SystemLuid = SYSTEM_LUID;
+ BOOLEAN CopyOnOpen, EffectiveOnly;
+ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
+
+ LookingForSystem = FALSE;
+
+ /* If LUID mapping is enable, try to get appropriate device map */
+ if (ObpLUIDDeviceMapsEnabled != 0)
+ {
+ /* In case of impersonation, we've got a bit of work to do */
+ CurrentThread = PsGetCurrentThread();
+ if (CurrentThread->ActiveImpersonationInfo)
+ {
+ /* Get impersonation token */
+ Token = PsReferenceImpersonationToken(CurrentThread,
+ &CopyOnOpen,
+ &EffectiveOnly,
+ &ImpersonationLevel);
+ /* Get logon LUID */
+ if (Token != NULL)
+ {
+ Status = SeQueryAuthenticationIdToken(Token, &LogonId);
+ }
+ else
+ {
+ /* Force failure */
+ Status = STATUS_NO_TOKEN;
+ }
+
+ /* If we got logon LUID */
+ if (NT_SUCCESS(Status))
+ {
+ /*
+ * Check it's not system, system is easy to handle,
+ * we just need to return ObSystemDeviceMap
+ */
+ if (!RtlEqualLuid(&LogonId, &SystemLuid))
+ {
+ /* Ask Se for the device map */
+ Status = SeGetLogonIdDeviceMap(&LogonId, &DeviceMap);
+ if (NT_SUCCESS(Status))
+ {
+ /* Acquire the device map lock */
+ KeAcquireGuardedMutex(&ObpDeviceMapLock);
+
+ /* Reference the device map if any */
+ if (DeviceMap != NULL)
+ {
+ ++DeviceMap->ReferenceCount;
+ }
+
+ /* Release the device map lock */
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
+
+ /* If we got the device map, we're done! */
+ if (DeviceMap != NULL)
+ {
+ ObDereferenceObject(Token);
+
+ return DeviceMap;
+ }
+ }
+ }
+ else
+ {
+ LookingForSystem = TRUE;
+ }
+ }
+ }
+
+ /*
+ * Fall back case of the LUID mapping, make sure there's a
+ * a device map attached to the current process
+ */
+ if (PsGetCurrentProcess()->DeviceMap == NULL &&
+ !NT_SUCCESS(ObpSetCurrentProcessDeviceMap()))
+ {
+ /* We may have failed after we got impersonation token */
+ if (Token != NULL)
+ {
+ ObDereferenceObject(Token);
+ }
+
+ return NULL;
+ }
+ }
+
+ /* Acquire the device map lock */
+ KeAcquireGuardedMutex(&ObpDeviceMapLock);
+
+ /* If we're looking for system map, use it */
+ if (LookingForSystem)
+ {
+ DeviceMap = ObSystemDeviceMap;
+ }
+ /* Otherwise, use current process device map */
+ else
+ {
+ DeviceMap = PsGetCurrentProcess()->DeviceMap;
+ }
+
+ /* If we got one, reference it */
+ if (DeviceMap != NULL)
+ {
+ ++DeviceMap->ReferenceCount;
+ }
+
+ /* Release the device map lock */
+ KeReleaseGuardedMutex(&ObpDeviceMapLock);
+
+ /* We may have impersonation token (if we failed in impersonation branch) */
+ if (Token != NULL)
+ {
+ ObDereferenceObject(Token);
+ }
+
+ /* Return the potentially found device map */
+ return DeviceMap;
}