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
|
|||
|
|