435 lines
11 KiB
C
435 lines
11 KiB
C
/*++
|
||
|
||
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
|
||
|