/* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/ob/devicemap.c * PURPOSE: Device map implementation * PROGRAMMERS: Eric Kohl (eric.kohl@reactos.org) * Alex Ionescu (alex.ionescu@reactos.org) */ /* INCLUDES ***************************************************************/ #include #define NDEBUG #include ULONG ObpLUIDDeviceMapsDisabled; ULONG ObpLUIDDeviceMapsEnabled; /* PRIVATE FUNCTIONS ******************************************************/ NTSTATUS NTAPI ObSetDeviceMap(IN PEPROCESS Process, IN HANDLE DirectoryHandle) { POBJECT_DIRECTORY DirectoryObject = NULL; PDEVICE_MAP DeviceMap = NULL, NewDeviceMap = NULL, OldDeviceMap; NTSTATUS Status; PEPROCESS WorkProcess; BOOLEAN MakePermanant = FALSE; Status = ObReferenceObjectByHandle(DirectoryHandle, DIRECTORY_TRAVERSE, ObpDirectoryObjectType, KeGetPreviousMode(), (PVOID*)&DirectoryObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT("ObReferenceObjectByHandle() failed (Status 0x%08lx)\n", Status); return Status; } /* Allocate and initialize a new device map */ DeviceMap = ExAllocatePoolWithTag(PagedPool, sizeof(*DeviceMap), 'mDbO'); if (DeviceMap == NULL) { ObDereferenceObject(DirectoryObject); return STATUS_INSUFFICIENT_RESOURCES; } /* Initialize the device map */ RtlZeroMemory(DeviceMap, sizeof(*DeviceMap)); DeviceMap->ReferenceCount = 1; DeviceMap->DosDevicesDirectory = DirectoryObject; /* Acquire the device map lock */ KeAcquireGuardedMutex(&ObpDeviceMapLock); /* Attach the device map to the directory object */ if (DirectoryObject->DeviceMap == NULL) { DirectoryObject->DeviceMap = DeviceMap; } else { NewDeviceMap = DeviceMap; /* There's already a device map, so reuse it */ DeviceMap = DirectoryObject->DeviceMap; ++DeviceMap->ReferenceCount; } /* Caller gave a process, use it */ if (Process != NULL) { WorkProcess = Process; } /* If no process given, use current and * set system device map */ else { WorkProcess = PsGetCurrentProcess(); ObSystemDeviceMap = DeviceMap; } /* If current object isn't system one, save system one in current * device map */ if (DirectoryObject != ObSystemDeviceMap->DosDevicesDirectory) { /* We also need to make the object permanant */ DeviceMap->GlobalDosDevicesDirectory = ObSystemDeviceMap->DosDevicesDirectory; MakePermanant = TRUE; } /* Save old process device map */ OldDeviceMap = WorkProcess->DeviceMap; /* Attach the device map to the process */ WorkProcess->DeviceMap = DeviceMap; /* Release the device map lock */ KeReleaseGuardedMutex(&ObpDeviceMapLock); /* If we have to make the object permamant, do it now */ if (MakePermanant) { POBJECT_HEADER ObjectHeader; POBJECT_HEADER_NAME_INFO HeaderNameInfo; ObjectHeader = OBJECT_TO_OBJECT_HEADER(DirectoryObject); HeaderNameInfo = ObpReferenceNameInfo(ObjectHeader); ObpEnterObjectTypeMutex(ObjectHeader->Type); if (HeaderNameInfo != NULL && HeaderNameInfo->Directory != NULL) { ObjectHeader->Flags |= OB_FLAG_PERMANENT; } ObpLeaveObjectTypeMutex(ObjectHeader->Type); if (HeaderNameInfo != NULL) { ObpDereferenceNameInfo(HeaderNameInfo); } } /* Release useless device map if required */ if (NewDeviceMap != NULL) { ObfDereferenceObject(DirectoryObject); ExFreePoolWithTag(NewDeviceMap, 'mDbO'); } /* And dereference previous process device map */ if (OldDeviceMap != NULL) { ObfDereferenceDeviceMap(OldDeviceMap); } return STATUS_SUCCESS; } PDEVICE_MAP NTAPI ObpReferenceDeviceMap(VOID) { UNIMPLEMENTED; return NULL; } VOID NTAPI ObDereferenceDeviceMap(IN PEPROCESS Process) { PDEVICE_MAP DeviceMap; DPRINT("ObDereferenceDeviceMap()\n"); /* Get the pointer to this process devicemap and reset it holding the device map lock */ KeAcquireGuardedMutex(&ObpDeviceMapLock); DeviceMap = Process->DeviceMap; Process->DeviceMap = NULL; KeReleaseGuardedMutex(&ObpDeviceMapLock); /* Continue only if there is a device map */ if (DeviceMap != NULL) ObfDereferenceDeviceMap(DeviceMap); } VOID FASTCALL ObfDereferenceDeviceMap(IN PDEVICE_MAP DeviceMap) { DPRINT("ObfDereferenceDeviceMap()\n"); /* Acquire the device map lock */ KeAcquireGuardedMutex(&ObpDeviceMapLock); /* Decrement the reference counter */ DeviceMap->ReferenceCount--; DPRINT("ReferenceCount: %lu\n", DeviceMap->ReferenceCount); /* Leave, if there are still references to this device map */ if (DeviceMap->ReferenceCount != 0) { /* Release the device map lock and leave */ KeReleaseGuardedMutex(&ObpDeviceMapLock); return; } /* Nobody is referencing it anymore, unlink the DOS directory */ DeviceMap->DosDevicesDirectory->DeviceMap = NULL; /* Release the devicemap lock */ KeReleaseGuardedMutex(&ObpDeviceMapLock); /* Dereference the DOS Devices Directory and free the Device Map */ ObMakeTemporaryObject(DeviceMap->DosDevicesDirectory); ObDereferenceObject(DeviceMap->DosDevicesDirectory); ExFreePoolWithTag(DeviceMap, 'mDbO'); } VOID NTAPI ObInheritDeviceMap(IN PEPROCESS Parent, IN PEPROCESS Process) { PDEVICE_MAP DeviceMap; DPRINT("ObInheritDeviceMap()\n"); /* Acquire the device map lock */ KeAcquireGuardedMutex(&ObpDeviceMapLock); /* Get the parent process device map or the system device map */ DeviceMap = (Parent != NULL) ? Parent->DeviceMap : ObSystemDeviceMap; if (DeviceMap != NULL) { /* Reference the device map and attach it to the new process */ DeviceMap->ReferenceCount++; DPRINT("ReferenceCount: %lu\n", DeviceMap->ReferenceCount); Process->DeviceMap = DeviceMap; } /* Release the device map lock */ KeReleaseGuardedMutex(&ObpDeviceMapLock); } NTSTATUS NTAPI ObQueryDeviceMapInformation(IN PEPROCESS Process, IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo, IN ULONG Flags) { PDEVICE_MAP DeviceMap = NULL, GlobalDeviceMap; BOOLEAN Dereference; PROCESS_DEVICEMAP_INFORMATION MapInfo; ULONG BitMask, i; BOOLEAN ReturnAny; NTSTATUS Status; /* Validate flags */ if (Flags & ~PROCESS_LUID_DOSDEVICES_ONLY) { return STATUS_INVALID_PARAMETER; } Dereference = FALSE; /* Do we want to return anything? */ ReturnAny = ~Flags & PROCESS_LUID_DOSDEVICES_ONLY; /* If LUID mappings are enabled... */ if (ObpLUIDDeviceMapsEnabled != 0) { /* Check for process parameter validness */ if (Process != NULL && Process != PsGetCurrentProcess()) { return STATUS_INVALID_PARAMETER; } /* And get the device map */ DeviceMap = ObpReferenceDeviceMap(); } /* Acquire the device map lock */ KeAcquireGuardedMutex(&ObpDeviceMapLock); /* * If we had a device map, if because of LUID mappings, * we'll have to dereference it afterwards */ if (DeviceMap != NULL) { Dereference = TRUE; } else { /* Get the process device map or the system device map */ DeviceMap = (Process != NULL) ? Process->DeviceMap : ObSystemDeviceMap; } /* Fail if no device map */ if (DeviceMap == NULL) { KeReleaseGuardedMutex(&ObpDeviceMapLock); return STATUS_END_OF_FILE; } /* At that point, assume success */ Status = STATUS_SUCCESS; /* Try to get the global device map if any */ GlobalDeviceMap = DeviceMap; if (DeviceMap->GlobalDosDevicesDirectory != NULL) { if (DeviceMap->GlobalDosDevicesDirectory->DeviceMap != NULL) { GlobalDeviceMap = DeviceMap->GlobalDosDevicesDirectory->DeviceMap; } } /* Now, setup our device map info, especially drive types */ MapInfo.Query.DriveMap = DeviceMap->DriveMap; /* Browse every device */ for (i = 0, BitMask = 1; i < 32; ++i, BitMask *= 2) { /* Set the type given current device map */ MapInfo.Query.DriveType[i] = DeviceMap->DriveType[i]; /* * If device is not existing and we're asked to return * more than just LUID mapped, get the entry * from global device map if not remote */ if (!(MapInfo.Query.DriveMap & BitMask) && ReturnAny) { if (ObpLUIDDeviceMapsEnabled != 0 || (GlobalDeviceMap->DriveType[i] != DOSDEVICE_DRIVE_REMOTE && GlobalDeviceMap->DriveType[i] != DOSDEVICE_DRIVE_CALCULATE)) { MapInfo.Query.DriveType[i] = GlobalDeviceMap->DriveType[i]; MapInfo.Query.DriveMap |= BitMask & GlobalDeviceMap->DriveMap; } } } /* Release the device map lock */ KeReleaseGuardedMutex(&ObpDeviceMapLock); /* Dereference LUID device map */ if (Dereference) { ObfDereferenceDeviceMap(DeviceMap); } /* Copy back data */ _SEH2_TRY { RtlCopyMemory(DeviceMapInfo, &MapInfo, sizeof(PROCESS_DEVICEMAP_INFORMATION)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; return Status; } ULONG NTAPI ObIsLUIDDeviceMapsEnabled(VOID) { return ObpLUIDDeviceMapsEnabled; } #if 0 NTSTATUS NTAPI ObIsDosDeviceLocallyMapped( IN ULONG Index, OUT PUCHAR DosDeviceState) { /* Check the index */ if (Index < 1 || Index > 26) return STATUS_INVALID_PARAMETER; /* Acquire the device map lock */ KeAcquireGuardedMutex(&ObpDeviceMapLock); /* Get drive mapping status */ *DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0; /* Release the device map lock */ KeReleaseGuardedMutex(&ObpDeviceMapLock); return STATUS_SUCCESS; } #endif /* EOF */