windows-nt/Source/XPSP1/NT/base/cluster/clusdisk/object.c

435 lines
11 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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