/*++ Copyright (c) 1992 Microsoft Corporation Module Name: object.c Abstract: Resource DLL for disks. Author: Rod Gamache (rodga) 18-Dec-1995 Revision History: --*/ #include "ntos.h" #include "zwapi.h" #include "windef.h" #include "stdio.h" #include "stdlib.h" #include "clusdskp.h" extern POBJECT_TYPE IoDeviceObjectType; #if 0 #define ATTR_DIR 0x00000001 #define ATTR_DEVICE 0x00000002 #define ATTR_FILE 0x00000004 #define ATTR_SYMLINK 0x00000008 #define DIRECTORYTYPE L"Directory" #define DEVICETYPE L"Device" #define FILETYPE L"File" #define SYMLINKTYPE L"SymbolicLink" #endif #ifdef ALLOC_PRAGMA //#pragma alloc_text(INIT, GetSymbolicLink) #endif // ALLOC_PRAGMA /* Converts the type-name into an attribute value */ #if 0 LONG CalcAttributes( PUNICODE_STRING Type ) { UNICODE_STRING TypeName; RtlInitUnicodeString(&TypeName, DIRECTORYTYPE); if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) { return ATTR_DIR; } RtlInitUnicodeString(&TypeName, DEVICETYPE); if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) { return ATTR_DEVICE; } RtlInitUnicodeString(&TypeName, FILETYPE); if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) { return ATTR_FILE; } RtlInitUnicodeString(&TypeName, SYMLINKTYPE); if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) { return ATTR_SYMLINK; } return(0); } // CalcAttributes #endif VOID GetSymbolicLink( IN PWCHAR RootName, IN OUT PWCHAR ObjectName // Assume this points at a MAX_PATH len buffer ) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE LinkHandle; WCHAR UnicodeBuffer[MAX_PATH]; WCHAR Buffer[MAX_PATH]; UNICODE_STRING UnicodeString; ULONG rootLen; ULONG objLen; rootLen = wcslen(RootName); objLen = wcslen(ObjectName); if ( (rootLen + objLen + 1) > ( sizeof(UnicodeBuffer)/sizeof(WCHAR) ) ) { *ObjectName = '\0'; return; } RtlZeroMemory( Buffer, sizeof(Buffer) ); wcsncpy( Buffer, RootName, rootLen ); wcsncat( Buffer, ObjectName, objLen ); // // Make the output buffer empty in case we fail. // *ObjectName = '\0'; RtlInitUnicodeString(&UnicodeString, Buffer); InitializeObjectAttributes(&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL ); // Open the given symbolic link object Status = ZwOpenSymbolicLinkObject(&LinkHandle, GENERIC_READ, &ObjectAttributes); if (!NT_SUCCESS(Status)) { ClusDiskPrint((1, "[ClusDisk] GetSymbolicLink: ZwOpenSymbolicLink " "failed, status = %08X., Name = [%ws]\n", Status, UnicodeString.Buffer)); return; } // Go get the target of the symbolic link UnicodeString.Length = 0; UnicodeString.Buffer = ObjectName; UnicodeString.MaximumLength = (USHORT)(MAX_PATH); Status = ZwQuerySymbolicLinkObject(LinkHandle, &UnicodeString, NULL); ZwClose(LinkHandle); if (!NT_SUCCESS(Status)) { ClusDiskPrint((1, "[ClusDisk] GetSymbolicLink: ZwQuerySymbolicLink failed, status = %08X.\n", Status)); return; } // Add NULL terminator UnicodeString.Buffer[UnicodeString.Length/sizeof(WCHAR)] = '\0'; return; } // GetSymbolicLink static WCHAR wszDosDevices[] = L"\\DosDevices\\A:"; NTSTATUS GetDriveLetterFromObjectDir( IN LPWSTR InputDeviceName, OUT PUCHAR Letter ) { UNICODE_STRING LinkName; UNICODE_STRING DeviceName; UNICODE_STRING UniDeviceName; OBJECT_ATTRIBUTES Obja; HANDLE LinkHandle; NTSTATUS Status; ULONG i; PWCHAR p; WCHAR DeviceNameBuffer[MAXIMUM_FILENAME_LENGTH]; RtlInitUnicodeString( &UniDeviceName, InputDeviceName ); RtlInitUnicodeString(&LinkName,wszDosDevices); p = (PWCHAR)LinkName.Buffer; p = p+12; for ( i=0; i<26; i++ ) { *p = (WCHAR)'A' + (WCHAR)i; InitializeObjectAttributes( &Obja, &LinkName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ZwOpenSymbolicLinkObject( &LinkHandle, SYMBOLIC_LINK_QUERY, &Obja ); if (NT_SUCCESS( Status )) { // // Open succeeded, Now get the link value // DeviceName.Length = 0; DeviceName.MaximumLength = sizeof(DeviceNameBuffer); DeviceName.Buffer = DeviceNameBuffer; Status = ZwQuerySymbolicLinkObject( LinkHandle, &DeviceName, NULL ); ZwClose(LinkHandle); if ( NT_SUCCESS(Status) ) { if ( RtlEqualUnicodeString(&UniDeviceName,&DeviceName,TRUE) ) { *Letter = (UCHAR)('A' + i); return(STATUS_SUCCESS); } } } } return(STATUS_NO_SUCH_FILE); } // GetDriveLetterFromObjectDir #if 0 PDEVICE_OBJECT GetDeviceObject( IN LPWSTR lpwstrDirectory, IN LPWSTR lpwstrObject, IN LPWSTR lpwstrType ) /*++ Routine Description: Find the device object given the directory, name and type. Arguments: Directory - the directory name for the object. Object - the object name. Type - the object type. Return Value: non-zero pointer to the device object NULL on failure --*/ { #define BUFFER_SIZE 2048 NTSTATUS Status; HANDLE DirectoryHandle; HANDLE ObjectHandle = NULL; ULONG Context = 0; ULONG ReturnedLength; CHAR Buffer[BUFFER_SIZE]; UNICODE_STRING ObjectName; UNICODE_STRING ObjectType; UNICODE_STRING DirectoryName; OBJECT_ATTRIBUTES Attributes; IO_STATUS_BLOCK IoStatusBlock; POBJECT_DIRECTORY_INFORMATION DirInfo; BOOL NotFound; UNICODE_STRING TypeName; // // Initialize strings // RtlInitUnicodeString( &ObjectType, lpwstrType ); RtlInitUnicodeString( &ObjectName, lpwstrObject ); RtlInitUnicodeString( &DirectoryName, lpwstrDirectory ); InitializeObjectAttributes( &Attributes, &DirectoryName, OBJ_CASE_INSENSITIVE, NULL, NULL ); if (!NT_SUCCESS( Status = ZwOpenDirectoryObject( &DirectoryHandle, STANDARD_RIGHTS_READ | DIRECTORY_QUERY | DIRECTORY_TRAVERSE, &Attributes ) )) { if (Status == STATUS_OBJECT_TYPE_MISMATCH) { ClusDiskPrint(( 1, "ClusDisk: OpenObject, <%wZ> is not a valid Object Directory Object name\n", &DirectoryName )); } else { ClusDiskPrint(( 1, "ClusDisk: OpenObject, failed to open directory, status = 0x%lx\n\r", Status )); } return NULL; } // // Query the entire directory in one sweep // NotFound = TRUE; for (Status = ZwQueryDirectoryObject( DirectoryHandle, Buffer, sizeof(Buffer), // LATER FALSE, TRUE, // one entry at a time for now TRUE, &Context, &ReturnedLength ); NotFound; Status = ZwQueryDirectoryObject( DirectoryHandle, Buffer, sizeof(Buffer), // LATER FALSE, TRUE, // one entry at a time for now FALSE, &Context, &ReturnedLength ) ) { // // Check the status of the operation. // if ( !NT_SUCCESS(Status) ) { break; } // // For every record in the buffer get the symbolic link and // compare the name of the symbolic link with the one we're // looking for. // // // Point to the first record in the buffer, we are guaranteed to have // one otherwise Status would have been No More Files // DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer; while ( DirInfo->Name.Length != 0 ) { ClusDiskPrint(( 1, "ClusDisk: Found object <%wZ>, Type <%wZ>\n", &(DirInfo->Name), &(DirInfo->TypeName) )); if (RtlEqualUnicodeString(&ObjectName, &DirInfo->Name, TRUE) && RtlEqualUnicodeString(&ObjectType, &DirInfo->TypeName, TRUE)) { NotFound = FALSE; break; } DirInfo++; } // while } // for ZwClose(DirectoryHandle); if ( NotFound ) { return(NULL); } InitializeObjectAttributes( &Attributes, &ObjectName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ZwOpenSymbolicLinkObject( &ObjectHandle, SYMBOLIC_LINK_ALL_ACCESS, &Attributes ); return(NULL); #if 0 // We now have the type of the object in ObjectType // We still have the full object name in lpstrObject // Use the appropriate open routine to get a handle sprintf( Buffer, "\\\\.\\%s", AnsiString.Buffer ); RtlInitAnsiString( &AnsiString, Buffer ); Status = RtlAnsiStringToUnicodeString(&ObjectName, &AnsiString, FALSE); ASSERT(NT_SUCCESS(Status)); InitializeObjectAttributes( &Attributes, &ObjectName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ZwOpenSymbolicLinkObject( &ObjectHandle, SYMBOLIC_LINK_ALL_ACCESS, &Attributes ); #if 0 Status = ZwOpenFile( &ObjectHandle, FILE_READ_ATTRIBUTES, &Attributes, &IoStatusBlock, 0, FILE_NON_DIRECTORY_FILE ); #endif if ( !NT_SUCCESS(Status) ) { ClusDiskPrint(( 1, "ClusDisk: OpenObject, open file failed, status %lx.\n", Status )); return(NULL); } #endif return(ObjectHandle); } // GetDeviceObject #endif