mirror of
https://github.com/reactos/reactos.git
synced 2025-06-25 00:19:43 +00:00
[NTOSKRNL] Rework ObpDeleteSymbolicLinkName and ObpCreateSymbolicLinkName
So that they handle LUID mappings and process device maps. Get rid of the ObpParseSymbolicLinkToIoDeviceObject helper and introduce a new helper ObpProcessDosDeviceSymbolicLink that will do the same things but also handle name creation/deletion as well as device map handling. All this is based on previous code (hence the same comments :-)). What's left to do now is to add support for device maps in ObpLookupObjectName
This commit is contained in:
parent
acc821e1ea
commit
f6eb13a969
1 changed files with 289 additions and 222 deletions
|
@ -20,288 +20,355 @@ POBJECT_TYPE ObpSymbolicLinkObjectType = NULL;
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
ObpProcessDosDeviceSymbolicLink(IN POBJECT_SYMBOLIC_LINK SymbolicLink,
|
||||||
ObpDeleteSymbolicLinkName(IN POBJECT_SYMBOLIC_LINK SymbolicLink)
|
IN BOOLEAN DeleteLink)
|
||||||
{
|
{
|
||||||
|
PDEVICE_MAP DeviceMap;
|
||||||
|
UNICODE_STRING TargetPath, LocalTarget;
|
||||||
|
POBJECT_DIRECTORY NameDirectory, DirectoryObject;
|
||||||
|
ULONG MaxReparse;
|
||||||
|
OBP_LOOKUP_CONTEXT LookupContext;
|
||||||
|
ULONG DriveType;
|
||||||
POBJECT_HEADER ObjectHeader;
|
POBJECT_HEADER ObjectHeader;
|
||||||
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
||||||
|
BOOLEAN DirectoryLocked;
|
||||||
|
PVOID Object;
|
||||||
|
|
||||||
/* FIXME: Need to support Device maps */
|
/*
|
||||||
|
* To prevent endless reparsing, setting an upper limit on the
|
||||||
|
* number of reparses.
|
||||||
|
*/
|
||||||
|
MaxReparse = 32;
|
||||||
|
NameDirectory = NULL;
|
||||||
|
|
||||||
/* Get header data */
|
/* Get header data */
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(SymbolicLink);
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(SymbolicLink);
|
||||||
ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
|
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||||
|
|
||||||
/* Check if we are not actually in a directory with a device map */
|
/* Check if we have a directory in our symlink to use */
|
||||||
if (!(ObjectNameInfo) ||
|
if (ObjectNameInfo != NULL)
|
||||||
!(ObjectNameInfo->Directory) /*||
|
|
||||||
!(ObjectNameInfo->Directory->DeviceMap)*/)
|
|
||||||
{
|
{
|
||||||
ObpDereferenceNameInfo(ObjectNameInfo);
|
NameDirectory = ObjectNameInfo->Directory;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if it's a DOS drive letter, and remove the entry from drive map if needed */
|
/* Initialize lookup context */
|
||||||
if (SymbolicLink->DosDeviceDriveIndex != 0 &&
|
ObpInitializeLookupContext(&LookupContext);
|
||||||
ObjectNameInfo->Name.Length == 2 * sizeof(WCHAR) &&
|
|
||||||
ObjectNameInfo->Name.Buffer[1] == L':' &&
|
/*
|
||||||
( (ObjectNameInfo->Name.Buffer[0] >= L'A' &&
|
* If we have to create the link, locate the IoDeviceObject if any
|
||||||
ObjectNameInfo->Name.Buffer[0] <= L'Z') ||
|
* this symbolic link points to.
|
||||||
(ObjectNameInfo->Name.Buffer[0] >= L'a' &&
|
*/
|
||||||
ObjectNameInfo->Name.Buffer[0] <= L'z') ))
|
if (SymbolicLink->LinkTargetObject != NULL || !DeleteLink)
|
||||||
{
|
{
|
||||||
/* Remove the drive entry */
|
/* Start the search from the root */
|
||||||
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
DirectoryObject = ObpRootDirectoryObject;
|
||||||
ObSystemDeviceMap->DriveType[SymbolicLink->DosDeviceDriveIndex-1] =
|
|
||||||
DOSDEVICE_DRIVE_UNKNOWN;
|
|
||||||
ObSystemDeviceMap->DriveMap &=
|
|
||||||
~(1 << (SymbolicLink->DosDeviceDriveIndex-1));
|
|
||||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
|
||||||
|
|
||||||
/* Reset the drive index, valid drive index starts from 1 */
|
/* Keep track of our progress while parsing the name */
|
||||||
SymbolicLink->DosDeviceDriveIndex = 0;
|
LocalTarget = SymbolicLink->LinkTarget;
|
||||||
}
|
|
||||||
|
|
||||||
ObpDereferenceNameInfo(ObjectNameInfo);
|
/* If LUID mappings are enabled, use system map */
|
||||||
}
|
if (ObpLUIDDeviceMapsEnabled != 0)
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
ObpParseSymbolicLinkToIoDeviceObject(IN POBJECT_DIRECTORY SymbolicLinkDirectory,
|
|
||||||
IN OUT POBJECT_DIRECTORY *Directory,
|
|
||||||
IN OUT PUNICODE_STRING TargetPath,
|
|
||||||
IN OUT POBP_LOOKUP_CONTEXT Context,
|
|
||||||
OUT PVOID *Object)
|
|
||||||
{
|
|
||||||
UNICODE_STRING Name;
|
|
||||||
BOOLEAN ManualUnlock;
|
|
||||||
|
|
||||||
if (! TargetPath || ! Object || ! Context || ! Directory ||
|
|
||||||
! SymbolicLinkDirectory)
|
|
||||||
{
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Need to support Device maps */
|
|
||||||
|
|
||||||
/* Try walking the target path and open each part of the path */
|
|
||||||
while (TargetPath->Length)
|
|
||||||
{
|
|
||||||
/* Strip '\' if present at the beginning of the target path */
|
|
||||||
if (TargetPath->Length >= sizeof(OBJ_NAME_PATH_SEPARATOR)&&
|
|
||||||
TargetPath->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
|
|
||||||
{
|
{
|
||||||
TargetPath->Buffer++;
|
DeviceMap = ObSystemDeviceMap;
|
||||||
TargetPath->Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
|
}
|
||||||
|
/* Otherwise, use the one in the process */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeviceMap = PsGetCurrentProcess()->DeviceMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember the current component of the target path */
|
ReparseTargetPath:
|
||||||
Name = *TargetPath;
|
/*
|
||||||
|
* If we have a device map active, check whether we have a drive
|
||||||
/* Move forward to the next component of the target path */
|
* letter prefixed with ??, if so, chomp it
|
||||||
while (TargetPath->Length >= sizeof(OBJ_NAME_PATH_SEPARATOR))
|
*/
|
||||||
|
if (DeviceMap != NULL)
|
||||||
{
|
{
|
||||||
if (TargetPath->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
|
if (!((ULONG_PTR)(LocalTarget.Buffer) & 7))
|
||||||
{
|
{
|
||||||
TargetPath->Buffer++;
|
if (DeviceMap->DosDevicesDirectory != NULL)
|
||||||
TargetPath->Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
|
{
|
||||||
|
if (LocalTarget.Length >= ObpDosDevicesShortName.Length &&
|
||||||
|
(*(PULONGLONG)LocalTarget.Buffer ==
|
||||||
|
ObpDosDevicesShortNamePrefix.Alignment.QuadPart))
|
||||||
|
{
|
||||||
|
DirectoryObject = DeviceMap->DosDevicesDirectory;
|
||||||
|
|
||||||
|
LocalTarget.Length -= ObpDosDevicesShortName.Length;
|
||||||
|
LocalTarget.Buffer += (ObpDosDevicesShortName.Length / sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try walking the target path and open each part of the path */
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
if (LocalTarget.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
|
||||||
|
{
|
||||||
|
++LocalTarget.Buffer;
|
||||||
|
LocalTarget.Length -= sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remember the current component of the target path */
|
||||||
|
TargetPath = LocalTarget;
|
||||||
|
|
||||||
|
/* Move forward to the next component of the target path */
|
||||||
|
if (LocalTarget.Length != 0)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (LocalTarget.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++LocalTarget.Buffer;
|
||||||
|
LocalTarget.Length -= sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
while (LocalTarget.Length != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetPath.Length -= LocalTarget.Length;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finished processing the entire path, stop
|
||||||
|
* That's a failure case, we quit here
|
||||||
|
*/
|
||||||
|
if (TargetPath.Length == 0)
|
||||||
|
{
|
||||||
|
ObpReleaseLookupContext(&LookupContext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure a deadlock does not occur as an exclusive lock on a pushlock
|
||||||
|
* would have already taken one in ObpLookupObjectName() on the parent
|
||||||
|
* directory where the symlink is being created [ObInsertObject()].
|
||||||
|
* Prevent recursive locking by faking lock state in the lookup context
|
||||||
|
* when the current directory is same as the parent directory where
|
||||||
|
* the symlink is being created. If the lock state is not faked,
|
||||||
|
* ObpLookupEntryDirectory() will try to get a recursive lock on the
|
||||||
|
* pushlock and hang. For e.g. this happens when a substed drive is pointed to
|
||||||
|
* another substed drive.
|
||||||
|
*/
|
||||||
|
if (DirectoryObject == NameDirectory)
|
||||||
|
{
|
||||||
|
DirectoryLocked = LookupContext.DirectoryLocked;
|
||||||
|
LookupContext.DirectoryLocked = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
DirectoryLocked = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object = ObpLookupEntryDirectory(DirectoryObject,
|
||||||
|
&TargetPath,
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
&LookupContext);
|
||||||
|
|
||||||
|
/* Locking was faked, undo it now */
|
||||||
|
if (DirectoryObject == NameDirectory)
|
||||||
|
{
|
||||||
|
LookupContext.DirectoryLocked = DirectoryLocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lookup failed, stop */
|
||||||
|
if (Object == NULL)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Name.Length -= TargetPath->Length;
|
/* If we don't have a directory object, we'll have to handle the object */
|
||||||
|
if (OBJECT_TO_OBJECT_HEADER(Object)->Type != ObpDirectoryObjectType)
|
||||||
|
{
|
||||||
|
/* If that's not a symbolic link, stop here, nothing to do */
|
||||||
|
if (OBJECT_TO_OBJECT_HEADER(Object)->Type != ObpSymbolicLinkObjectType ||
|
||||||
|
(((POBJECT_SYMBOLIC_LINK)Object)->DosDeviceDriveIndex != 0))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Finished processing the entire path, stop */
|
/* We're out of reparse attempts */
|
||||||
if (! Name.Length)
|
if (MaxReparse == 0)
|
||||||
break;
|
{
|
||||||
|
Object = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
--MaxReparse;
|
||||||
* Make sure a deadlock does not occur as an exclusive lock on a pushlock
|
|
||||||
* would have already taken one in ObpLookupObjectName() on the parent
|
|
||||||
* directory where the symlink is being created [ObInsertObject()].
|
|
||||||
* Prevent recursive locking by faking lock state in the lookup context
|
|
||||||
* when the current directory is same as the parent directory where
|
|
||||||
* the symlink is being created. If the lock state is not faked,
|
|
||||||
* ObpLookupEntryDirectory() will try to get a recursive lock on the
|
|
||||||
* pushlock and hang. For e.g. this happens when a substed drive is pointed to
|
|
||||||
* another substed drive.
|
|
||||||
*/
|
|
||||||
if (*Directory == SymbolicLinkDirectory && ! Context->DirectoryLocked)
|
|
||||||
{
|
|
||||||
/* Fake lock state so that ObpLookupEntryDirectory() doesn't attempt a lock */
|
|
||||||
ManualUnlock = TRUE;
|
|
||||||
Context->DirectoryLocked = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ManualUnlock = FALSE;
|
|
||||||
|
|
||||||
*Object = ObpLookupEntryDirectory(*Directory,
|
/* Symlink points to another initialized symlink, ask caller to reparse */
|
||||||
&Name,
|
DirectoryObject = ObpRootDirectoryObject;
|
||||||
0,
|
|
||||||
FALSE,
|
|
||||||
Context);
|
|
||||||
|
|
||||||
/* Locking was faked, undo it now */
|
LocalTarget = ((POBJECT_SYMBOLIC_LINK)Object)->LinkTarget;
|
||||||
if (*Directory == SymbolicLinkDirectory && ManualUnlock)
|
|
||||||
Context->DirectoryLocked = FALSE;
|
|
||||||
|
|
||||||
/* Lookup failed, stop */
|
goto ReparseTargetPath;
|
||||||
if (! *Object)
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
if (OBJECT_TO_OBJECT_HEADER(*Object)->Type == ObpDirectoryObjectType)
|
|
||||||
{
|
|
||||||
/* Make this current directory, and continue search */
|
/* Make this current directory, and continue search */
|
||||||
*Directory = (POBJECT_DIRECTORY)*Object;
|
DirectoryObject = Object;
|
||||||
}
|
|
||||||
else if (OBJECT_TO_OBJECT_HEADER(*Object)->Type == ObpSymbolicLinkObjectType &&
|
|
||||||
(((POBJECT_SYMBOLIC_LINK)*Object)->DosDeviceDriveIndex == 0))
|
|
||||||
{
|
|
||||||
/* Symlink points to another initialized symlink, ask caller to reparse */
|
|
||||||
*Directory = ObpRootDirectoryObject;
|
|
||||||
TargetPath = &((POBJECT_SYMBOLIC_LINK)*Object)->LinkTarget;
|
|
||||||
return STATUS_REPARSE_OBJECT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Neither directory or symlink, stop */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a valid object, only if object type is IoDeviceObject */
|
DeviceMap = NULL;
|
||||||
if (*Object &&
|
/* That's a drive letter, find a suitable device map */
|
||||||
OBJECT_TO_OBJECT_HEADER(*Object)->Type != IoDeviceObjectType)
|
if (SymbolicLink->DosDeviceDriveIndex != 0)
|
||||||
{
|
{
|
||||||
*Object = NULL;
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(SymbolicLink);
|
||||||
|
ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
|
||||||
|
if (ObjectNameInfo != NULL)
|
||||||
|
{
|
||||||
|
if (ObjectNameInfo->Directory != NULL)
|
||||||
|
{
|
||||||
|
DeviceMap = ObjectNameInfo->Directory->DeviceMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObpDereferenceNameInfo(ObjectNameInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return STATUS_SUCCESS;
|
|
||||||
|
/* If we were asked to delete the symlink */
|
||||||
|
if (DeleteLink)
|
||||||
|
{
|
||||||
|
/* Zero its target */
|
||||||
|
RtlInitUnicodeString(&SymbolicLink->LinkTargetRemaining, NULL);
|
||||||
|
|
||||||
|
/* If we had a target objected, dereference it */
|
||||||
|
if (SymbolicLink->LinkTargetObject != NULL)
|
||||||
|
{
|
||||||
|
ObDereferenceObject(SymbolicLink->LinkTargetObject);
|
||||||
|
SymbolicLink->LinkTargetObject = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If it was a drive letter */
|
||||||
|
if (DeviceMap != NULL)
|
||||||
|
{
|
||||||
|
/* Acquire the device map lock */
|
||||||
|
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||||
|
|
||||||
|
/* Remove the drive entry */
|
||||||
|
DeviceMap->DriveType[SymbolicLink->DosDeviceDriveIndex - 1] =
|
||||||
|
DOSDEVICE_DRIVE_UNKNOWN;
|
||||||
|
DeviceMap->DriveMap &=
|
||||||
|
~(1 << (SymbolicLink->DosDeviceDriveIndex - 1));
|
||||||
|
|
||||||
|
/* Release the device map lock */
|
||||||
|
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||||
|
|
||||||
|
/* Reset the drive index, valid drive index starts from 1 */
|
||||||
|
SymbolicLink->DosDeviceDriveIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DriveType = DOSDEVICE_DRIVE_CALCULATE;
|
||||||
|
|
||||||
|
/* If we have a drive letter and a pointer device object */
|
||||||
|
if (Object != NULL && SymbolicLink->DosDeviceDriveIndex != 0 &&
|
||||||
|
OBJECT_TO_OBJECT_HEADER(Object)->Type == IoDeviceObjectType)
|
||||||
|
{
|
||||||
|
/* Calculate the drive type */
|
||||||
|
switch(((PDEVICE_OBJECT)Object)->DeviceType)
|
||||||
|
{
|
||||||
|
case FILE_DEVICE_VIRTUAL_DISK:
|
||||||
|
DriveType = DOSDEVICE_DRIVE_RAMDISK;
|
||||||
|
break;
|
||||||
|
case FILE_DEVICE_CD_ROM:
|
||||||
|
case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
|
||||||
|
DriveType = DOSDEVICE_DRIVE_CDROM;
|
||||||
|
break;
|
||||||
|
case FILE_DEVICE_DISK:
|
||||||
|
case FILE_DEVICE_DISK_FILE_SYSTEM:
|
||||||
|
case FILE_DEVICE_FILE_SYSTEM:
|
||||||
|
if (((PDEVICE_OBJECT)Object)->Characteristics & FILE_REMOVABLE_MEDIA)
|
||||||
|
DriveType = DOSDEVICE_DRIVE_REMOVABLE;
|
||||||
|
else
|
||||||
|
DriveType = DOSDEVICE_DRIVE_FIXED;
|
||||||
|
break;
|
||||||
|
case FILE_DEVICE_NETWORK:
|
||||||
|
case FILE_DEVICE_NETWORK_FILE_SYSTEM:
|
||||||
|
DriveType = DOSDEVICE_DRIVE_REMOTE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DPRINT1("Device Type %lu for %wZ is not known or unhandled\n",
|
||||||
|
((PDEVICE_OBJECT)Object)->DeviceType,
|
||||||
|
&SymbolicLink->LinkTarget);
|
||||||
|
DriveType = DOSDEVICE_DRIVE_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a new drive entry */
|
||||||
|
if (DeviceMap != NULL)
|
||||||
|
{
|
||||||
|
/* Acquire the device map lock */
|
||||||
|
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||||
|
|
||||||
|
DeviceMap->DriveType[SymbolicLink->DosDeviceDriveIndex - 1] =
|
||||||
|
(UCHAR)DriveType;
|
||||||
|
DeviceMap->DriveMap |=
|
||||||
|
1 << (SymbolicLink->DosDeviceDriveIndex - 1);
|
||||||
|
|
||||||
|
/* Release the device map lock */
|
||||||
|
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
ObpReleaseLookupContext(&LookupContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
ObpDeleteSymbolicLinkName(IN POBJECT_SYMBOLIC_LINK SymbolicLink)
|
||||||
|
{
|
||||||
|
/* Just call the helper */
|
||||||
|
ObpProcessDosDeviceSymbolicLink(SymbolicLink, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ObpCreateSymbolicLinkName(IN POBJECT_SYMBOLIC_LINK SymbolicLink)
|
ObpCreateSymbolicLinkName(IN POBJECT_SYMBOLIC_LINK SymbolicLink)
|
||||||
{
|
{
|
||||||
|
WCHAR UpperDrive;
|
||||||
POBJECT_HEADER ObjectHeader;
|
POBJECT_HEADER ObjectHeader;
|
||||||
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
||||||
PVOID Object = NULL;
|
|
||||||
POBJECT_DIRECTORY Directory;
|
|
||||||
UNICODE_STRING TargetPath;
|
|
||||||
NTSTATUS Status;
|
|
||||||
ULONG DriveType = DOSDEVICE_DRIVE_CALCULATE;
|
|
||||||
ULONG ReparseCnt;
|
|
||||||
const ULONG MaxReparseAttempts = 20;
|
|
||||||
OBP_LOOKUP_CONTEXT Context;
|
|
||||||
|
|
||||||
/* FIXME: Need to support Device maps */
|
|
||||||
|
|
||||||
/* Get header data */
|
/* Get header data */
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(SymbolicLink);
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(SymbolicLink);
|
||||||
ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
|
ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
|
||||||
|
|
||||||
/* Check if we are not actually in a directory with a device map */
|
/* No name info, nothing to create */
|
||||||
if (!(ObjectNameInfo) ||
|
if (ObjectNameInfo == NULL)
|
||||||
!(ObjectNameInfo->Directory) /*||
|
|
||||||
!(ObjectNameInfo->Directory->DeviceMap)*/)
|
|
||||||
{
|
{
|
||||||
ObpDereferenceNameInfo(ObjectNameInfo);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if it's a DOS drive letter, and set the drive index accordingly */
|
/* If we have a device map, look for creating a letter based drive */
|
||||||
if (ObjectNameInfo->Name.Length == 2 * sizeof(WCHAR) &&
|
if (ObjectNameInfo->Directory != NULL &&
|
||||||
ObjectNameInfo->Name.Buffer[1] == L':' &&
|
ObjectNameInfo->Directory->DeviceMap != NULL)
|
||||||
( (ObjectNameInfo->Name.Buffer[0] >= L'A' &&
|
|
||||||
ObjectNameInfo->Name.Buffer[0] <= L'Z') ||
|
|
||||||
(ObjectNameInfo->Name.Buffer[0] >= L'a' &&
|
|
||||||
ObjectNameInfo->Name.Buffer[0] <= L'z') ))
|
|
||||||
{
|
{
|
||||||
SymbolicLink->DosDeviceDriveIndex =
|
/* Is it a drive letter based name? */
|
||||||
RtlUpcaseUnicodeChar(ObjectNameInfo->Name.Buffer[0]) - L'A';
|
if (ObjectNameInfo->Name.Length == 2 * sizeof(WCHAR))
|
||||||
/* The Drive index start from 1 */
|
|
||||||
SymbolicLink->DosDeviceDriveIndex++;
|
|
||||||
|
|
||||||
/* Initialize lookup context */
|
|
||||||
ObpInitializeLookupContext(&Context);
|
|
||||||
|
|
||||||
/* Start the search from the root */
|
|
||||||
Directory = ObpRootDirectoryObject;
|
|
||||||
TargetPath = SymbolicLink->LinkTarget;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Locate the IoDeviceObject if any this symbolic link points to.
|
|
||||||
* To prevent endless reparsing, setting an upper limit on the
|
|
||||||
* number of reparses.
|
|
||||||
*/
|
|
||||||
Status = STATUS_REPARSE_OBJECT;
|
|
||||||
ReparseCnt = 0;
|
|
||||||
while (Status == STATUS_REPARSE_OBJECT &&
|
|
||||||
ReparseCnt < MaxReparseAttempts)
|
|
||||||
{
|
{
|
||||||
Status =
|
if (ObjectNameInfo->Name.Buffer[1] == L':')
|
||||||
ObpParseSymbolicLinkToIoDeviceObject(ObjectNameInfo->Directory,
|
|
||||||
&Directory,
|
|
||||||
&TargetPath,
|
|
||||||
&Context,
|
|
||||||
&Object);
|
|
||||||
if (Status == STATUS_REPARSE_OBJECT)
|
|
||||||
ReparseCnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cleanup lookup context */
|
|
||||||
ObpReleaseLookupContext(&Context);
|
|
||||||
|
|
||||||
/* Error, or max resparse attemtps exceeded */
|
|
||||||
if (! NT_SUCCESS(Status) || ReparseCnt >= MaxReparseAttempts)
|
|
||||||
{
|
|
||||||
/* Cleanup */
|
|
||||||
ObpDereferenceNameInfo(ObjectNameInfo);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object)
|
|
||||||
{
|
|
||||||
/* Calculate the drive type */
|
|
||||||
switch(((PDEVICE_OBJECT)Object)->DeviceType)
|
|
||||||
{
|
{
|
||||||
case FILE_DEVICE_VIRTUAL_DISK:
|
UpperDrive = RtlUpcaseUnicodeChar(ObjectNameInfo->Name.Buffer[0]);
|
||||||
DriveType = DOSDEVICE_DRIVE_RAMDISK;
|
if (UpperDrive >= L'A' && UpperDrive <= L'Z')
|
||||||
break;
|
{
|
||||||
case FILE_DEVICE_CD_ROM:
|
/* Compute its index (it's 1 based - 0 means no letter) */
|
||||||
case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
|
SymbolicLink->DosDeviceDriveIndex = UpperDrive - (L'A' - 1);
|
||||||
DriveType = DOSDEVICE_DRIVE_CDROM;
|
}
|
||||||
break;
|
|
||||||
case FILE_DEVICE_DISK:
|
|
||||||
case FILE_DEVICE_DISK_FILE_SYSTEM:
|
|
||||||
case FILE_DEVICE_FILE_SYSTEM:
|
|
||||||
if (((PDEVICE_OBJECT)Object)->Characteristics & FILE_REMOVABLE_MEDIA)
|
|
||||||
DriveType = DOSDEVICE_DRIVE_REMOVABLE;
|
|
||||||
else
|
|
||||||
DriveType = DOSDEVICE_DRIVE_FIXED;
|
|
||||||
break;
|
|
||||||
case FILE_DEVICE_NETWORK:
|
|
||||||
case FILE_DEVICE_NETWORK_FILE_SYSTEM:
|
|
||||||
DriveType = DOSDEVICE_DRIVE_REMOTE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DPRINT1("Device Type %lu for %wZ is not known or unhandled\n",
|
|
||||||
((PDEVICE_OBJECT)Object)->DeviceType,
|
|
||||||
&SymbolicLink->LinkTarget);
|
|
||||||
DriveType = DOSDEVICE_DRIVE_UNKNOWN;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a new drive entry */
|
/* Call the helper */
|
||||||
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
ObpProcessDosDeviceSymbolicLink(SymbolicLink, FALSE);
|
||||||
ObSystemDeviceMap->DriveType[SymbolicLink->DosDeviceDriveIndex-1] =
|
|
||||||
(UCHAR)DriveType;
|
|
||||||
ObSystemDeviceMap->DriveMap |=
|
|
||||||
1 << (SymbolicLink->DosDeviceDriveIndex-1);
|
|
||||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup */
|
/* We're done */
|
||||||
ObpDereferenceNameInfo(ObjectNameInfo);
|
ObpDereferenceNameInfo(ObjectNameInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue