Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693/* * 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) * Pierre Schweitzer (pierre@reactos.org) */
/* INCLUDES ***************************************************************/
#include <ntoskrnl.h>#define NDEBUG#include <debug.h>
ULONG ObpLUIDDeviceMapsDisabled;ULONG ObpLUIDDeviceMapsEnabled;
/* PRIVATE FUNCTIONS ******************************************************/
NTSTATUSNTAPIObSetDeviceMap(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) { ObDereferenceObject(DirectoryObject); ExFreePoolWithTag(NewDeviceMap, 'mDbO'); }
/* And dereference previous process device map */ if (OldDeviceMap != NULL) { ObfDereferenceDeviceMap(OldDeviceMap); }
return STATUS_SUCCESS;}
NTSTATUSNTAPIObSetDirectoryDeviceMap(OUT PDEVICE_MAP * DeviceMap, IN HANDLE DirectoryHandle){ POBJECT_DIRECTORY DirectoryObject = NULL; PDEVICE_MAP LocalMap = NULL, NewDeviceMap = NULL; NTSTATUS Status; POBJECT_HEADER ObjectHeader; POBJECT_HEADER_NAME_INFO HeaderNameInfo;
Status = ObReferenceObjectByHandle(DirectoryHandle, DIRECTORY_TRAVERSE, ObpDirectoryObjectType, KernelMode, (PVOID*)&DirectoryObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT("ObReferenceObjectByHandle() failed (Status 0x%08lx)\n", Status); return Status; }
/* Allocate and initialize a new device map */ LocalMap = ExAllocatePoolWithTag(PagedPool, sizeof(*LocalMap), 'mDbO'); if (LocalMap == NULL) { ObDereferenceObject(DirectoryObject); return STATUS_INSUFFICIENT_RESOURCES; }
/* Initialize the device map */ RtlZeroMemory(LocalMap, sizeof(*LocalMap)); LocalMap->ReferenceCount = 1; LocalMap->DosDevicesDirectory = DirectoryObject;
/* Acquire the device map lock */ KeAcquireGuardedMutex(&ObpDeviceMapLock);
/* Attach the device map to the directory object */ if (DirectoryObject->DeviceMap == NULL) { DirectoryObject->DeviceMap = LocalMap; } else { NewDeviceMap = LocalMap;
/* There's already a device map, so reuse it */ LocalMap = DirectoryObject->DeviceMap; ++LocalMap->ReferenceCount; }
/* 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 */ LocalMap->GlobalDosDevicesDirectory = ObSystemDeviceMap->DosDevicesDirectory; }
/* Release the device map lock */ KeReleaseGuardedMutex(&ObpDeviceMapLock);
if (DeviceMap != NULL) { *DeviceMap = LocalMap; }
/* Caller expects us to make the object permanant, so do it! */ 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) { ObDereferenceObject(DirectoryObject); ExFreePoolWithTag(NewDeviceMap, 'mDbO'); }
return Status;}
NTSTATUSNTAPIObpSetCurrentProcessDeviceMap(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_MAPNTAPIObpReferenceDeviceMap(VOID){ 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;}
VOIDNTAPIObDereferenceDeviceMap(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);}
VOIDFASTCALLObfDereferenceDeviceMap(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');}
VOIDNTAPIObInheritDeviceMap(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);}
NTSTATUSNTAPIObQueryDeviceMapInformation( _In_opt_ PEPROCESS Process, _Out_ 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;}
ULONGNTAPIObIsLUIDDeviceMapsEnabled(VOID){ return ObpLUIDDeviceMapsEnabled;}
#if 0NTSTATUSNTAPIObIsDosDeviceLocallyMapped( 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 */