rdpdr/disk: add query file/fs information irp processing.
This commit is contained in:
parent
9d349a2667
commit
12215d0e0a
@ -26,6 +26,7 @@
|
||||
#include <fnmatch.h>
|
||||
#include <utime.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
@ -39,6 +40,17 @@
|
||||
#include "rdpdr_types.h"
|
||||
#include "disk_file.h"
|
||||
|
||||
#define FILE_TIME_SYSTEM_TO_RDP(_t) \
|
||||
(((uint64)(_t) + 11644473600LL) * 10000000LL)
|
||||
#define FILE_TIME_RDP_TO_SYSTEM(_t) \
|
||||
(((_t) == 0LL || (_t) == (uint64)(-1LL)) ? 0 : (time_t)((_t) / 10000000LL - 11644473600LL))
|
||||
|
||||
#define FILE_ATTR_SYSTEM_TO_RDP(_f, _st) ( \
|
||||
(S_ISDIR(_st.st_mode) ? FILE_ATTRIBUTE_DIRECTORY : 0) | \
|
||||
(_f->filename[0] == '.' ? FILE_ATTRIBUTE_HIDDEN : 0) | \
|
||||
(_f->delete_pending ? FILE_ATTRIBUTE_TEMPORARY : 0) | \
|
||||
(st.st_mode & S_IWUSR ? 0 : FILE_ATTRIBUTE_READONLY))
|
||||
|
||||
static char* disk_file_get_fullpath(const char* base_path, const char* path)
|
||||
{
|
||||
char* fullpath;
|
||||
@ -203,6 +215,11 @@ DISK_FILE* disk_file_new(const char* base_path, const char* path, uint32 id,
|
||||
file = xnew(DISK_FILE);
|
||||
file->id = id;
|
||||
file->fullpath = disk_file_get_fullpath(base_path, path);
|
||||
file->filename = strrchr(file->fullpath, '/');
|
||||
if (file->filename == NULL)
|
||||
file->filename = file->fullpath;
|
||||
else
|
||||
file->filename += 1;
|
||||
file->fd = -1;
|
||||
|
||||
if (!disk_file_init(file, DesiredAccess, CreateDisposition, CreateOptions))
|
||||
@ -264,7 +281,6 @@ boolean disk_file_write(DISK_FILE* file, uint8* buffer, uint32 Length)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
|
||||
if (file->is_dir || file->fd == -1)
|
||||
return False;
|
||||
|
||||
@ -279,3 +295,54 @@ boolean disk_file_write(DISK_FILE* file, uint8* buffer, uint32 Length)
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
boolean disk_file_query_information(DISK_FILE* file, uint32 FsInformationClass, STREAM* output)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(file->fullpath, &st) != 0)
|
||||
{
|
||||
stream_write_uint32(output, 0); /* Length */
|
||||
return False;
|
||||
}
|
||||
switch (FsInformationClass)
|
||||
{
|
||||
case FileBasicInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
|
||||
stream_write_uint32(output, 40); /* Length */
|
||||
stream_check_size(output, 40);
|
||||
stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */
|
||||
stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */
|
||||
stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */
|
||||
stream_write_uint64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */
|
||||
stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
|
||||
stream_write_uint32(output, 0); /* Reserved */
|
||||
break;
|
||||
|
||||
case FileStandardInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232088.aspx */
|
||||
stream_write_uint32(output, 24); /* Length */
|
||||
stream_check_size(output, 24);
|
||||
stream_write_uint64(output, st.st_size); /* AllocationSize */
|
||||
stream_write_uint64(output, st.st_size); /* EndOfFile */
|
||||
stream_write_uint32(output, st.st_nlink); /* NumberOfLinks */
|
||||
stream_write_uint8(output, file->delete_pending ? 1 : 0); /* DeletePending */
|
||||
stream_write_uint8(output, file->is_dir ? 1 : 0); /* Directory */
|
||||
stream_write_uint16(output, 0); /* Reserved */
|
||||
break;
|
||||
|
||||
case FileAttributeTagInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232093.aspx */
|
||||
stream_write_uint32(output, 8); /* Length */
|
||||
stream_check_size(output, 8);
|
||||
stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
|
||||
stream_write_uint32(output, 0); /* ReparseTag */
|
||||
break;
|
||||
|
||||
default:
|
||||
stream_write_uint32(output, 0); /* Length */
|
||||
DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
|
||||
return False;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
@ -29,11 +29,11 @@ typedef struct _DISK_FILE DISK_FILE;
|
||||
struct _DISK_FILE
|
||||
{
|
||||
uint32 id;
|
||||
uint32 attr;
|
||||
boolean is_dir;
|
||||
int fd;
|
||||
DIR* dir;
|
||||
char* fullpath;
|
||||
char* filename;
|
||||
char* pattern;
|
||||
boolean delete_pending;
|
||||
};
|
||||
@ -45,5 +45,6 @@ void disk_file_free(DISK_FILE* file);
|
||||
boolean disk_file_seek(DISK_FILE* file, uint64 Offset);
|
||||
boolean disk_file_read(DISK_FILE* file, uint8* buffer, uint32* Length);
|
||||
boolean disk_file_write(DISK_FILE* file, uint8* buffer, uint32 Length);
|
||||
boolean disk_file_query_information(DISK_FILE* file, uint32 FsInformationClass, STREAM* output);
|
||||
|
||||
#endif /* __DISK_FILE_H */
|
||||
|
@ -147,6 +147,8 @@ static void disk_process_irp_close(DISK_DEVICE* disk, IRP* irp)
|
||||
}
|
||||
|
||||
stream_write(irp->output, "\0\0\0\0\0", 5); /* Padding(5) */
|
||||
|
||||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp)
|
||||
@ -187,6 +189,10 @@ static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp)
|
||||
|
||||
DEBUG_WARN("read %s(%d) failed.", file->fullpath, file->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SVC("read %u-%u from %s(%d).", Offset, Offset + Length, file->fullpath, file->id);
|
||||
}
|
||||
}
|
||||
|
||||
stream_write_uint32(irp->output, Length);
|
||||
@ -196,6 +202,8 @@ static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp)
|
||||
stream_write(irp->output, buffer, Length);
|
||||
}
|
||||
xfree(buffer);
|
||||
|
||||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_write(DISK_DEVICE* disk, IRP* irp)
|
||||
@ -231,9 +239,117 @@ static void disk_process_irp_write(DISK_DEVICE* disk, IRP* irp)
|
||||
|
||||
DEBUG_WARN("write %s(%d) failed.", file->fullpath, file->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SVC("write %u-%u to %s(%d).", Offset, Offset + Length, file->fullpath, file->id);
|
||||
}
|
||||
|
||||
stream_write_uint32(irp->output, Length);
|
||||
stream_write_uint8(irp->output, 0); /* Padding */
|
||||
|
||||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_query_information(DISK_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
DISK_FILE* file;
|
||||
uint32 FsInformationClass;
|
||||
|
||||
stream_read_uint32(irp->input, FsInformationClass);
|
||||
|
||||
file = disk_get_file_by_id(disk, irp->FileId);
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
|
||||
DEBUG_WARN("FileId %d not valid.", irp->FileId);
|
||||
}
|
||||
else if (!disk_file_query_information(file, FsInformationClass, irp->output))
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
|
||||
DEBUG_WARN("query_information %s(%d) failed.", file->fullpath, file->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SVC("query_information %d on %s(%d).", FsInformationClass, file->fullpath, file->id);
|
||||
}
|
||||
|
||||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_query_volume_information(DISK_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
uint32 FsInformationClass;
|
||||
STREAM* output = irp->output;
|
||||
|
||||
stream_read_uint32(irp->input, FsInformationClass);
|
||||
|
||||
switch (FsInformationClass)
|
||||
{
|
||||
case FileFsVolumeInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232108.aspx */
|
||||
stream_write_uint32(output, 34); /* Length */
|
||||
stream_check_size(output, 34);
|
||||
stream_write_uint64(output, 0); /* VolumeCreationTime */
|
||||
stream_write_uint32(output, 0); /* VolumeSerialNumber */
|
||||
stream_write_uint32(output, 16); /* VolumeLabelLength */
|
||||
stream_write_uint8(output, 0); /* SupportsObjects */
|
||||
stream_write_uint8(output, 0); /* Reserved */
|
||||
stream_write(output, "F\0R\0E\0E\0R\0D\0P\0\0\0", 16); /* VolumeLabel (Unicode) */
|
||||
break;
|
||||
|
||||
case FileFsSizeInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232107.aspx */
|
||||
stream_write_uint32(output, 24); /* Length */
|
||||
stream_check_size(output, 24);
|
||||
stream_write_uint64(output, 0x1000000); /* TotalAllocationUnits */
|
||||
stream_write_uint64(output, 0x800000); /* AvailableAllocationUnits */
|
||||
stream_write_uint32(output, 1); /* SectorsPerAllocationUnit */
|
||||
stream_write_uint32(output, 0x400); /* BytesPerSector */
|
||||
break;
|
||||
|
||||
case FileFsAttributeInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232101.aspx */
|
||||
stream_write_uint32(output, 22); /* Length */
|
||||
stream_check_size(output, 22);
|
||||
stream_write_uint32(output,
|
||||
FILE_CASE_SENSITIVE_SEARCH |
|
||||
FILE_CASE_PRESERVED_NAMES |
|
||||
FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
|
||||
stream_write_uint32(output, 510); /* MaximumComponentNameLength */
|
||||
stream_write_uint32(output, 10); /* FileSystemNameLength */
|
||||
stream_write(output, "F\0A\0T\03\02\0", 10); /* FileSystemName */
|
||||
break;
|
||||
|
||||
case FileFsFullSizeInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232104.aspx */
|
||||
stream_write_uint32(output, 32); /* Length */
|
||||
stream_check_size(output, 32);
|
||||
stream_write_uint64(output, 0x1000000); /* TotalAllocationUnits */
|
||||
stream_write_uint64(output, 0x800000); /* CallerAvailableAllocationUnits */
|
||||
stream_write_uint64(output, 0x800000); /* ActualAvailableAllocationUnits */
|
||||
stream_write_uint32(output, 1); /* SectorsPerAllocationUnit */
|
||||
stream_write_uint32(output, 0x400); /* BytesPerSector */
|
||||
break;
|
||||
|
||||
case FileFsDeviceInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232109.aspx */
|
||||
stream_write_uint32(output, 8); /* Length */
|
||||
stream_check_size(output, 8);
|
||||
stream_write_uint32(output, FILE_DEVICE_DISK); /* DeviceType */
|
||||
stream_write_uint32(output, 0); /* Characteristics */
|
||||
break;
|
||||
|
||||
default:
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
stream_write_uint32(output, 0); /* Length */
|
||||
DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
|
||||
break;
|
||||
}
|
||||
|
||||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
|
||||
@ -256,6 +372,14 @@ static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
|
||||
disk_process_irp_write(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_QUERY_INFORMATION:
|
||||
disk_process_irp_query_information(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
||||
disk_process_irp_query_volume_information(disk, irp);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
|
||||
irp->IoStatus = STATUS_NOT_SUPPORTED;
|
||||
|
Loading…
Reference in New Issue
Block a user