mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
Sam Arun Raj Seeniraj:
[NTOSKRNL.EXE] - Complemented existing stub routines ObpDeleteSymbolicLinkName() and ObpCreateSymbolicLinkName(). Now when symbolic links are created, they are checked for dos drive mapping and ObSystemDeviceMap is updated accordingly. - Updates to ObpDeviceMapLock are protected by a guarded mutex (changed from fast mutex by Aleksey Bragin). - Aleksey Bragin: Fix concurrent access issues in ObDereferenceDeviceMap. The DeviceMap read/write operation must be atomic (within the ObpDeviceMapLock region). [SUBST.EXE] - Removed hard coded strings and moved it to resource file. [WIN32CSR.DLL] - Added a workaround, when target path end with a trailing '\', the substituted drive fails to parse to the target, this is a bug in the object manager, but working around it in CsrDefineDosDevice() by stripping trailing '\'. See issue #993 for more details. svn path=/trunk/; revision=51452
This commit is contained in:
parent
f34a5b0b2d
commit
3d60cef193
13 changed files with 399 additions and 58 deletions
16
reactos/base/system/subst/lang/en-US.rc
Normal file
16
reactos/base/system/subst/lang/en-US.rc
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "resource.h"
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_INCORRECT_PARAMETER_COUNT "Incorrect number of parameters - %s\n"
|
||||
IDS_INVALID_PARAMETER "Incorrect number of parameters - %s\n"
|
||||
IDS_INVALID_PARAMETER2 "Invalid parameter - %s\n"
|
||||
IDS_DRIVE_ALREAD_SUBSTED "Drive already SUBSTed\n"
|
||||
IDS_FAILED_WITH_ERROCODE "Failed with error code 0x%x: %s\n"
|
||||
IDS_USAGE "Associates a path with a drive letter.\n\nSUBST [drive1: [drive2:]path]\nSUBST drive1: /D\n\n drive1: \
|
||||
Specifies a virtual drive to which you want to assign a path.\n \
|
||||
[drive2:]path Specifies a physical drive and path you want to assign to\n \
|
||||
a virtual drive.\n /D \
|
||||
Deletes a substituted (virtual) drive.\n\nType SUBST with no parameters to display a list of current virtual drives.\n"
|
||||
END
|
11
reactos/base/system/subst/resource.h
Normal file
11
reactos/base/system/subst/resource.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#define RC_STRING_MAX_SIZE 2048
|
||||
|
||||
/* Strings */
|
||||
#define IDS_FAILED_WITH_ERROCODE 1001
|
||||
#define IDS_USAGE 1002
|
||||
#define IDS_INCORRECT_PARAMETER_COUNT 1003
|
||||
#define IDS_INVALID_PARAMETER 1004
|
||||
#define IDS_INVALID_PARAMETER2 1005
|
||||
#define IDS_DRIVE_ALREAD_SUBSTED 1006
|
||||
|
||||
/* EOF */
|
6
reactos/base/system/subst/rsrc.rc
Normal file
6
reactos/base/system/subst/rsrc.rc
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
|
||||
#include "lang/en-US.rc"
|
|
@ -14,11 +14,13 @@
|
|||
#include <tchar.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#include "resource.h"
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
void PrintError(DWORD ErrCode)
|
||||
{
|
||||
TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
|
||||
TCHAR *buffer = (TCHAR*) calloc(2048,
|
||||
sizeof(TCHAR));
|
||||
TCHAR *msg = NULL;
|
||||
|
@ -32,9 +34,13 @@ void PrintError(DWORD ErrCode)
|
|||
(TCHAR*)&msg,
|
||||
0,
|
||||
NULL);
|
||||
LoadString(GetModuleHandle(NULL),
|
||||
IDS_FAILED_WITH_ERROCODE,
|
||||
szFmtString,
|
||||
sizeof(szFmtString) / sizeof(szFmtString[0]));
|
||||
_sntprintf(buffer,
|
||||
2048,
|
||||
_T("Failed with error code 0x%x: %s\n"),
|
||||
szFmtString,
|
||||
ErrCode,
|
||||
msg);
|
||||
_tprintf(_T("%s"),
|
||||
|
@ -45,16 +51,15 @@ void PrintError(DWORD ErrCode)
|
|||
}
|
||||
}
|
||||
|
||||
void DisplaySubstUsage()
|
||||
void DisplaySubstUsage(void)
|
||||
{
|
||||
_tprintf(_T("Associates a path with a drive letter.\n\n"));
|
||||
_tprintf(_T("SUBST [drive1: [drive2:]path]\n"));
|
||||
_tprintf(_T("SUBST drive1: /D\n\n"));
|
||||
_tprintf(_T(" drive1: Specifies a virtual drive to which you want to assign a path.\n"));
|
||||
_tprintf(_T(" [drive2:]path Specifies a physical drive and path you want to assign to\n"));
|
||||
_tprintf(_T(" a virtual drive.\n"));
|
||||
_tprintf(_T(" /D Deletes a substituted (virtual) drive.\n\n"));
|
||||
_tprintf(_T("Type SUBST with no parameters to display a list of current virtual drives.\n"));
|
||||
TCHAR szHelp[RC_STRING_MAX_SIZE] = {0};
|
||||
|
||||
LoadString(GetModuleHandle(NULL),
|
||||
IDS_USAGE,
|
||||
szHelp,
|
||||
sizeof(szHelp) / sizeof(szHelp[0]));
|
||||
_tprintf(_T("%s"), szHelp);
|
||||
}
|
||||
|
||||
BOOLEAN IsSubstedDrive(TCHAR *Drive)
|
||||
|
@ -103,7 +108,7 @@ BOOLEAN IsSubstedDrive(TCHAR *Drive)
|
|||
return Result;
|
||||
}
|
||||
|
||||
void DumpSubstedDrives()
|
||||
void DumpSubstedDrives(void)
|
||||
{
|
||||
TCHAR Drive[3] = _T("A:");
|
||||
LPTSTR lpTargetPath = NULL;
|
||||
|
@ -161,17 +166,23 @@ void DumpSubstedDrives()
|
|||
int DeleteSubst(TCHAR* Drive)
|
||||
{
|
||||
BOOL Result;
|
||||
TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
|
||||
|
||||
LoadString(GetModuleHandle(NULL),
|
||||
IDS_INVALID_PARAMETER2,
|
||||
szFmtString,
|
||||
sizeof(szFmtString) / sizeof(szFmtString[0]));
|
||||
|
||||
if (_tcslen(Drive) > 2)
|
||||
{
|
||||
_tprintf(_T("Invalid parameter - %s\n"),
|
||||
_tprintf(szFmtString,
|
||||
Drive);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (! IsSubstedDrive(Drive))
|
||||
{
|
||||
_tprintf(_T("Invalid Parameter - %s\n"),
|
||||
_tprintf(szFmtString,
|
||||
Drive);
|
||||
return 1;
|
||||
}
|
||||
|
@ -190,17 +201,33 @@ int DeleteSubst(TCHAR* Drive)
|
|||
int AddSubst(TCHAR* Drive, TCHAR *Path)
|
||||
{
|
||||
BOOL Result;
|
||||
TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
|
||||
|
||||
if (_tcslen(Drive) > 2)
|
||||
LoadString(GetModuleHandle(NULL),
|
||||
IDS_INVALID_PARAMETER2,
|
||||
szFmtString,
|
||||
sizeof(szFmtString) / sizeof(szFmtString[0]));
|
||||
if (_tcslen(Drive) != 2)
|
||||
{
|
||||
_tprintf(_T("Invalid parameter - %s\n"),
|
||||
_tprintf(szFmtString,
|
||||
Drive);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (Drive[1] != _T(':'))
|
||||
{
|
||||
_tprintf(szFmtString,
|
||||
Drive);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (IsSubstedDrive(Drive))
|
||||
{
|
||||
_tprintf(_T("Drive already SUBSTed\n"));
|
||||
LoadString(GetModuleHandle(NULL),
|
||||
IDS_DRIVE_ALREAD_SUBSTED,
|
||||
szFmtString,
|
||||
sizeof(szFmtString) / sizeof(szFmtString[0]));
|
||||
_tprintf(szFmtString);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -218,6 +245,7 @@ int AddSubst(TCHAR* Drive, TCHAR *Path)
|
|||
int _tmain(int argc, TCHAR* argv[])
|
||||
{
|
||||
INT i;
|
||||
TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
|
@ -232,7 +260,11 @@ int _tmain(int argc, TCHAR* argv[])
|
|||
{
|
||||
if (argc >= 2)
|
||||
{
|
||||
_tprintf(_T("Invalid parameter - %s\n"),
|
||||
LoadString(GetModuleHandle(NULL),
|
||||
IDS_INVALID_PARAMETER,
|
||||
szFmtString,
|
||||
sizeof(szFmtString) / sizeof(szFmtString[0]));
|
||||
_tprintf(szFmtString,
|
||||
argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
@ -242,7 +274,11 @@ int _tmain(int argc, TCHAR* argv[])
|
|||
|
||||
if (argc > 3)
|
||||
{
|
||||
_tprintf(_T("Incorrect number of parameters - %s\n"),
|
||||
LoadString(GetModuleHandle(NULL),
|
||||
IDS_INCORRECT_PARAMETER_COUNT,
|
||||
szFmtString,
|
||||
sizeof(szFmtString) / sizeof(szFmtString[0]));
|
||||
_tprintf(szFmtString,
|
||||
argv[3]);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="subst" type="win32cui" installbase="system32" installname="subst.exe" >
|
||||
<module name="subst" type="win32cui" installbase="system32" installname="subst.exe" unicode="yes">
|
||||
<include base="ReactOS">include/reactos/wine</include>
|
||||
<include base="subst">.</include>
|
||||
<library>kernel32</library>
|
||||
<library>user32</library>
|
||||
<file>subst.c</file>
|
||||
<file>subst.rc</file>
|
||||
</module>
|
||||
|
|
|
@ -3,3 +3,5 @@
|
|||
#define REACTOS_STR_INTERNAL_NAME "subst\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "subst.exe\0"
|
||||
#include <reactos/version.rc>
|
||||
|
||||
#include "rsrc.rc"
|
||||
|
|
|
@ -64,17 +64,20 @@ HalpAssignDrive(IN PUNICODE_STRING PartitionName,
|
|||
if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 26))
|
||||
{
|
||||
/* Force assignment */
|
||||
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||
if ((ObSystemDeviceMap->DriveMap & (1 << DriveNumber)) != 0)
|
||||
{
|
||||
DbgPrint("Drive letter already used!\n");
|
||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||
return FALSE;
|
||||
}
|
||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Automatic assignment */
|
||||
DriveNumber = AUTO_DRIVE;
|
||||
|
||||
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||
for (i = 2; i < 26; i++)
|
||||
{
|
||||
if ((ObSystemDeviceMap->DriveMap & (1 << i)) == 0)
|
||||
|
@ -83,6 +86,7 @@ HalpAssignDrive(IN PUNICODE_STRING PartitionName,
|
|||
break;
|
||||
}
|
||||
}
|
||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||
|
||||
if (DriveNumber == AUTO_DRIVE)
|
||||
{
|
||||
|
@ -93,10 +97,6 @@ HalpAssignDrive(IN PUNICODE_STRING PartitionName,
|
|||
|
||||
DPRINT("DriveNumber %d\n", DriveNumber);
|
||||
|
||||
/* Update the System Device Map */
|
||||
ObSystemDeviceMap->DriveMap |= (1 << DriveNumber);
|
||||
ObSystemDeviceMap->DriveType[DriveNumber] = DriveType;
|
||||
|
||||
/* Build drive name */
|
||||
swprintf(DriveNameBuffer,
|
||||
L"\\??\\%C:",
|
||||
|
|
|
@ -578,6 +578,7 @@ ObGetProcessHandleCount(
|
|||
//
|
||||
extern ULONG ObpTraceLevel;
|
||||
extern KEVENT ObpDefaultObject;
|
||||
extern KGUARDED_MUTEX ObpDeviceMapLock;
|
||||
extern POBJECT_TYPE ObpTypeObjectType;
|
||||
extern POBJECT_TYPE ObSymbolicLinkType;
|
||||
extern POBJECT_TYPE ObpTypeObjectType;
|
||||
|
|
|
@ -169,6 +169,9 @@ ObInitSystem(VOID)
|
|||
/* Initialize the Default Event */
|
||||
KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE);
|
||||
|
||||
/* Initialize the Dos Device Map mutex */
|
||||
KeInitializeGuardedMutex(&ObpDeviceMapLock);
|
||||
|
||||
/* Setup default access for the system process */
|
||||
PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS;
|
||||
PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS;
|
||||
|
|
|
@ -21,6 +21,7 @@ extern ULONG NtGlobalFlag;
|
|||
|
||||
POBJECT_TYPE ObpTypeObjectType = NULL;
|
||||
KEVENT ObpDefaultObject;
|
||||
KGUARDED_MUTEX ObpDeviceMapLock;
|
||||
|
||||
GENERAL_LOOKASIDE ObpNameBufferLookasideList, ObpCreateInfoLookasideList;
|
||||
|
||||
|
@ -107,7 +108,7 @@ ObpDeallocateObject(IN PVOID Object)
|
|||
/* Add the SD charge too */
|
||||
if (Header->Flags & OB_FLAG_SECURITY) PagedPoolCharge += 2048;
|
||||
}
|
||||
|
||||
|
||||
/* Return the quota */
|
||||
DPRINT("FIXME: Should return quotas: %lx %lx\n", PagedPoolCharge, NonPagedPoolCharge);
|
||||
#if 0
|
||||
|
@ -115,7 +116,7 @@ ObpDeallocateObject(IN PVOID Object)
|
|||
PagedPoolCharge,
|
||||
NonPagedPoolCharge);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1261,14 +1262,14 @@ ObpDeleteObjectType(IN PVOID Object)
|
|||
{
|
||||
ULONG i;
|
||||
POBJECT_TYPE ObjectType = (PVOID)Object;
|
||||
|
||||
|
||||
/* Loop our locks */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
/* Delete each one */
|
||||
ExDeleteResourceLite(&ObjectType->ObjectLocks[i]);
|
||||
}
|
||||
|
||||
|
||||
/* Delete our main mutex */
|
||||
ExDeleteResourceLite(&ObjectType->Mutex);
|
||||
}
|
||||
|
|
|
@ -23,8 +23,160 @@ VOID
|
|||
NTAPI
|
||||
ObpDeleteSymbolicLinkName(IN POBJECT_SYMBOLIC_LINK SymbolicLink)
|
||||
{
|
||||
/* FIXME: Device maps not supported yet */
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
||||
|
||||
/* FIXME: Need to support Device maps */
|
||||
|
||||
/* Get header data */
|
||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(SymbolicLink);
|
||||
ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
|
||||
|
||||
/* Check if we are not actually in a directory with a device map */
|
||||
if (!(ObjectNameInfo) ||
|
||||
!(ObjectNameInfo->Directory) /*||
|
||||
!(ObjectNameInfo->Directory->DeviceMap)*/)
|
||||
{
|
||||
ObpDereferenceNameInfo(ObjectNameInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if it's a DOS drive letter, and remove the entry from drive map if needed */
|
||||
if (SymbolicLink->DosDeviceDriveIndex != 0 &&
|
||||
ObjectNameInfo->Name.Length == 2 * sizeof(WCHAR) &&
|
||||
ObjectNameInfo->Name.Buffer[1] == L':' &&
|
||||
( (ObjectNameInfo->Name.Buffer[0] >= L'A' &&
|
||||
ObjectNameInfo->Name.Buffer[0] <= L'Z') ||
|
||||
(ObjectNameInfo->Name.Buffer[0] >= L'a' &&
|
||||
ObjectNameInfo->Name.Buffer[0] <= L'z') ))
|
||||
{
|
||||
/* Remove the drive entry */
|
||||
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||
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 */
|
||||
SymbolicLink->DosDeviceDriveIndex = 0;
|
||||
}
|
||||
|
||||
ObpDereferenceNameInfo(ObjectNameInfo);
|
||||
}
|
||||
|
||||
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++;
|
||||
TargetPath->Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
/* Remember the current component of the target path */
|
||||
Name = *TargetPath;
|
||||
|
||||
/* Move forward to the next component of the target path */
|
||||
while (TargetPath->Length >= sizeof(OBJ_NAME_PATH_SEPARATOR))
|
||||
{
|
||||
if (TargetPath->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
|
||||
{
|
||||
TargetPath->Buffer++;
|
||||
TargetPath->Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
Name.Length -= TargetPath->Length;
|
||||
|
||||
/* Finished processing the entire path, stop */
|
||||
if (! Name.Length)
|
||||
break;
|
||||
|
||||
/*
|
||||
* 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,
|
||||
&Name,
|
||||
0,
|
||||
FALSE,
|
||||
Context);
|
||||
|
||||
/* Locking was faked, undo it now */
|
||||
if (*Directory == SymbolicLinkDirectory && ManualUnlock)
|
||||
Context->DirectoryLocked = FALSE;
|
||||
|
||||
/* Lookup failed, stop */
|
||||
if (! *Object)
|
||||
break;
|
||||
|
||||
if (OBJECT_TO_OBJECT_HEADER(*Object)->Type == ObDirectoryType)
|
||||
{
|
||||
/* Make this current directory, and continue search */
|
||||
*Directory = (POBJECT_DIRECTORY)*Object;
|
||||
}
|
||||
else if (OBJECT_TO_OBJECT_HEADER(*Object)->Type == ObSymbolicLinkType &&
|
||||
(((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 */
|
||||
if (*Object &&
|
||||
OBJECT_TO_OBJECT_HEADER(*Object)->Type != IoDeviceObjectType)
|
||||
{
|
||||
*Object = NULL;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -33,23 +185,124 @@ ObpCreateSymbolicLinkName(IN POBJECT_SYMBOLIC_LINK SymbolicLink)
|
|||
{
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
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 */
|
||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(SymbolicLink);
|
||||
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||
ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
|
||||
|
||||
/* Check if we are not actually in a directory with a device map */
|
||||
if (!(ObjectNameInfo) ||
|
||||
!(ObjectNameInfo->Directory) ||
|
||||
!(ObjectNameInfo->Directory->DeviceMap))
|
||||
!(ObjectNameInfo->Directory) /*||
|
||||
!(ObjectNameInfo->Directory->DeviceMap)*/)
|
||||
{
|
||||
/* There's nothing to do, return */
|
||||
ObpDereferenceNameInfo(ObjectNameInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: We don't support device maps yet */
|
||||
DPRINT1("Unhandled path!\n");
|
||||
ASSERT(FALSE);
|
||||
/* Check if it's a DOS drive letter, and set the drive index accordingly */
|
||||
if (ObjectNameInfo->Name.Length == 2 * sizeof(WCHAR) &&
|
||||
ObjectNameInfo->Name.Buffer[1] == L':' &&
|
||||
( (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 =
|
||||
RtlUpcaseUnicodeChar(ObjectNameInfo->Name.Buffer[0]) - L'A';
|
||||
/* 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 =
|
||||
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:
|
||||
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 %ld for %wZ is not known or unhandled\n",
|
||||
((PDEVICE_OBJECT)Object)->DeviceType,
|
||||
&SymbolicLink->LinkTarget);
|
||||
DriveType = DOSDEVICE_DRIVE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a new drive entry */
|
||||
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||
ObSystemDeviceMap->DriveType[SymbolicLink->DosDeviceDriveIndex-1] =
|
||||
(UCHAR)DriveType;
|
||||
ObSystemDeviceMap->DriveMap |=
|
||||
1 << (SymbolicLink->DosDeviceDriveIndex-1);
|
||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||
}
|
||||
|
||||
/* Cleanup */
|
||||
ObpDereferenceNameInfo(ObjectNameInfo);
|
||||
}
|
||||
|
||||
/*++
|
||||
|
|
|
@ -113,24 +113,28 @@ VOID
|
|||
NTAPI
|
||||
ObDereferenceDeviceMap(IN PEPROCESS Process)
|
||||
{
|
||||
//KIRQL OldIrql;
|
||||
PDEVICE_MAP DeviceMap = Process->DeviceMap;
|
||||
PDEVICE_MAP DeviceMap;
|
||||
|
||||
/* FIXME: We don't use Process Devicemaps yet */
|
||||
/* Get the pointer to this process devicemap and reset it
|
||||
holding devicemap lock */
|
||||
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||
DeviceMap = Process->DeviceMap;
|
||||
Process->DeviceMap = NULL;
|
||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||
|
||||
/* Continue only if there is a devicemap to dereference */
|
||||
if (DeviceMap)
|
||||
{
|
||||
/* FIXME: Acquire the DeviceMap Spinlock */
|
||||
// KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
|
||||
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||
|
||||
/* Delete the device map link and dereference it */
|
||||
Process->DeviceMap = NULL;
|
||||
if (--DeviceMap->ReferenceCount)
|
||||
{
|
||||
/* Nobody is referencing it anymore, unlink the DOS directory */
|
||||
DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
|
||||
|
||||
/* FIXME: Release the DeviceMap Spinlock */
|
||||
// KeReleasepinLock(DeviceMap->Lock, OldIrql);
|
||||
/* Release the devicemap lock */
|
||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||
|
||||
/* Dereference the DOS Devices Directory and free the Device Map */
|
||||
ObDereferenceObject(DeviceMap->DosDevicesDirectory);
|
||||
|
@ -138,8 +142,8 @@ ObDereferenceDeviceMap(IN PEPROCESS Process)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Release the DeviceMap Spinlock */
|
||||
// KeReleasepinLock(DeviceMap->Lock, OldIrql);
|
||||
/* Release the devicemap lock */
|
||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1144,15 +1148,12 @@ NTAPI
|
|||
ObQueryDeviceMapInformation(IN PEPROCESS Process,
|
||||
IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
|
||||
{
|
||||
//KIRQL OldIrql ;
|
||||
|
||||
/*
|
||||
* FIXME: This is an ugly hack for now, to always return the System Device Map
|
||||
* instead of returning the Process Device Map. Not important yet since we don't use it
|
||||
*/
|
||||
|
||||
/* FIXME: Acquire the DeviceMap Spinlock */
|
||||
// KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
|
||||
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||
|
||||
/* Make a copy */
|
||||
DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
|
||||
|
@ -1160,8 +1161,7 @@ ObQueryDeviceMapInformation(IN PEPROCESS Process,
|
|||
ObSystemDeviceMap->DriveType,
|
||||
sizeof(ObSystemDeviceMap->DriveType));
|
||||
|
||||
/* FIXME: Release the DeviceMap Spinlock */
|
||||
// KeReleasepinLock(DeviceMap->Lock, OldIrql);
|
||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -59,7 +59,7 @@ CSR_API(CsrDefineDosDevice)
|
|||
DWORD dwFlags;
|
||||
PWSTR lpBuffer;
|
||||
|
||||
DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
|
||||
DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
|
||||
Request->Data.DefineDosDeviceRequest.dwFlags,
|
||||
&Request->Data.DefineDosDeviceRequest.DeviceName,
|
||||
&Request->Data.DefineDosDeviceRequest.TargetName);
|
||||
|
@ -98,6 +98,17 @@ CSR_API(CsrDefineDosDevice)
|
|||
|
||||
RequestLinkTarget =
|
||||
&Request->Data.DefineDosDeviceRequest.TargetName;
|
||||
/*
|
||||
* Strip off any trailing '\', if we leave a trailing slash the drive remains non-accessible.
|
||||
* So working around it for now.
|
||||
* FIXME: Need to fix this in the object manager ObpLookupObjectName()??, and remove this when the its fixed.
|
||||
*/
|
||||
while (RequestLinkTarget->Length >= sizeof(WCHAR) &&
|
||||
RequestLinkTarget->Buffer[(RequestLinkTarget->Length/sizeof(WCHAR)) - 1] == L'\\')
|
||||
{
|
||||
RequestLinkTarget->Length -= sizeof(WCHAR);
|
||||
}
|
||||
|
||||
lpBuffer = (PWSTR) RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
RequestDeviceName.MaximumLength + 5 * sizeof(WCHAR));
|
||||
|
@ -146,7 +157,7 @@ CSR_API(CsrDefineDosDevice)
|
|||
&LinkTarget,
|
||||
&Length);
|
||||
}
|
||||
|
||||
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)\n",
|
||||
|
@ -188,7 +199,7 @@ CSR_API(CsrDefineDosDevice)
|
|||
CONTAINING_RECORD(Entry,
|
||||
CSRSS_DOS_DEVICE_HISTORY_ENTRY,
|
||||
Entry);
|
||||
Matched =
|
||||
Matched =
|
||||
! RtlCompareUnicodeString(&RequestDeviceName,
|
||||
&HistoryEntry->Device,
|
||||
FALSE);
|
||||
|
@ -459,7 +470,7 @@ CSR_API(CsrDefineDosDevice)
|
|||
&DeviceName, Status);
|
||||
}
|
||||
}
|
||||
_SEH2_FINALLY
|
||||
_SEH2_FINALLY
|
||||
{
|
||||
(void) RtlLeaveCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
if (DeviceName.Buffer)
|
||||
|
@ -504,13 +515,13 @@ CSR_API(CsrDefineDosDevice)
|
|||
return Status;
|
||||
}
|
||||
|
||||
void CsrCleanupDefineDosDevice()
|
||||
void CsrCleanupDefineDosDevice(void)
|
||||
{
|
||||
PLIST_ENTRY Entry, ListHead;
|
||||
PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry;
|
||||
|
||||
(void) RtlDeleteCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
|
||||
|
||||
ListHead = &DosDeviceHistory;
|
||||
Entry = ListHead->Flink;
|
||||
while (Entry != ListHead)
|
||||
|
|
Loading…
Reference in a new issue