From 3d60cef1931e2c6f5cfade6546595c994c743241 Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Mon, 25 Apr 2011 16:08:00 +0000 Subject: [PATCH] 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 --- reactos/base/system/subst/lang/en-US.rc | 16 ++ reactos/base/system/subst/resource.h | 11 + reactos/base/system/subst/rsrc.rc | 6 + reactos/base/system/subst/subst.c | 72 +++-- reactos/base/system/subst/subst.rbuild | 3 +- reactos/base/system/subst/subst.rc | 2 + reactos/ntoskrnl/fstub/disksup.c | 10 +- reactos/ntoskrnl/include/internal/ob.h | 1 + reactos/ntoskrnl/ob/obinit.c | 3 + reactos/ntoskrnl/ob/oblife.c | 9 +- reactos/ntoskrnl/ob/oblink.c | 269 +++++++++++++++++- reactos/ntoskrnl/ob/obname.c | 32 +-- .../subsystems/win32/csrss/win32csr/file.c | 23 +- 13 files changed, 399 insertions(+), 58 deletions(-) create mode 100644 reactos/base/system/subst/lang/en-US.rc create mode 100644 reactos/base/system/subst/resource.h create mode 100644 reactos/base/system/subst/rsrc.rc diff --git a/reactos/base/system/subst/lang/en-US.rc b/reactos/base/system/subst/lang/en-US.rc new file mode 100644 index 00000000000..790555b2db2 --- /dev/null +++ b/reactos/base/system/subst/lang/en-US.rc @@ -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 diff --git a/reactos/base/system/subst/resource.h b/reactos/base/system/subst/resource.h new file mode 100644 index 00000000000..9baa5b31a61 --- /dev/null +++ b/reactos/base/system/subst/resource.h @@ -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 */ diff --git a/reactos/base/system/subst/rsrc.rc b/reactos/base/system/subst/rsrc.rc new file mode 100644 index 00000000000..a6f84e411dc --- /dev/null +++ b/reactos/base/system/subst/rsrc.rc @@ -0,0 +1,6 @@ +#include +#include "resource.h" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#include "lang/en-US.rc" diff --git a/reactos/base/system/subst/subst.c b/reactos/base/system/subst/subst.c index 7cb92563eb8..3bfad0cae3e 100644 --- a/reactos/base/system/subst/subst.c +++ b/reactos/base/system/subst/subst.c @@ -14,11 +14,13 @@ #include #define NDEBUG #include +#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; } diff --git a/reactos/base/system/subst/subst.rbuild b/reactos/base/system/subst/subst.rbuild index fe93acb95e1..8b77abd857d 100644 --- a/reactos/base/system/subst/subst.rbuild +++ b/reactos/base/system/subst/subst.rbuild @@ -1,9 +1,10 @@ - + include/reactos/wine . kernel32 + user32 subst.c subst.rc diff --git a/reactos/base/system/subst/subst.rc b/reactos/base/system/subst/subst.rc index b81ea2c6a7b..db0df66fd9d 100644 --- a/reactos/base/system/subst/subst.rc +++ b/reactos/base/system/subst/subst.rc @@ -3,3 +3,5 @@ #define REACTOS_STR_INTERNAL_NAME "subst\0" #define REACTOS_STR_ORIGINAL_FILENAME "subst.exe\0" #include + +#include "rsrc.rc" diff --git a/reactos/ntoskrnl/fstub/disksup.c b/reactos/ntoskrnl/fstub/disksup.c index 7c4f651f8ff..c4a67c3413f 100644 --- a/reactos/ntoskrnl/fstub/disksup.c +++ b/reactos/ntoskrnl/fstub/disksup.c @@ -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:", diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index 521bf5834a4..532565ee390 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -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; diff --git a/reactos/ntoskrnl/ob/obinit.c b/reactos/ntoskrnl/ob/obinit.c index 5a24101ed45..37d6f1bc761 100644 --- a/reactos/ntoskrnl/ob/obinit.c +++ b/reactos/ntoskrnl/ob/obinit.c @@ -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; diff --git a/reactos/ntoskrnl/ob/oblife.c b/reactos/ntoskrnl/ob/oblife.c index f87e5948d36..ad4d9f10ca3 100644 --- a/reactos/ntoskrnl/ob/oblife.c +++ b/reactos/ntoskrnl/ob/oblife.c @@ -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); } diff --git a/reactos/ntoskrnl/ob/oblink.c b/reactos/ntoskrnl/ob/oblink.c index 5b147474c0c..3648aa797a5 100644 --- a/reactos/ntoskrnl/ob/oblink.c +++ b/reactos/ntoskrnl/ob/oblink.c @@ -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); } /*++ diff --git a/reactos/ntoskrnl/ob/obname.c b/reactos/ntoskrnl/ob/obname.c index a514af7b195..e4f7e184985 100644 --- a/reactos/ntoskrnl/ob/obname.c +++ b/reactos/ntoskrnl/ob/obname.c @@ -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 */ diff --git a/reactos/subsystems/win32/csrss/win32csr/file.c b/reactos/subsystems/win32/csrss/win32csr/file.c index 862a01480f3..982e8feec54 100644 --- a/reactos/subsystems/win32/csrss/win32csr/file.c +++ b/reactos/subsystems/win32/csrss/win32csr/file.c @@ -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)