rdpdr/disk: add set_information and device_control irp processing.
This commit is contained in:
parent
0ac3d908f5
commit
cc3160cb9d
@ -23,7 +23,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <utime.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <freerdp/utils/memory.h>
|
#include <freerdp/utils/memory.h>
|
||||||
#include <freerdp/utils/stream.h>
|
#include <freerdp/utils/stream.h>
|
||||||
#include <freerdp/utils/svc_plugin.h>
|
#include <freerdp/utils/svc_plugin.h>
|
||||||
@ -50,7 +51,7 @@
|
|||||||
(_f->delete_pending ? FILE_ATTRIBUTE_TEMPORARY : 0) | \
|
(_f->delete_pending ? FILE_ATTRIBUTE_TEMPORARY : 0) | \
|
||||||
(st.st_mode & S_IWUSR ? 0 : FILE_ATTRIBUTE_READONLY))
|
(st.st_mode & S_IWUSR ? 0 : FILE_ATTRIBUTE_READONLY))
|
||||||
|
|
||||||
static char* disk_file_get_fullpath(const char* base_path, const char* path)
|
static char* disk_file_combine_fullpath(const char* base_path, const char* path)
|
||||||
{
|
{
|
||||||
char* fullpath;
|
char* fullpath;
|
||||||
int len;
|
int len;
|
||||||
@ -131,7 +132,18 @@ static boolean disk_file_remove_dir(const char* path)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean disk_file_init(DISK_FILE* file, uint32 DesiredAccess, uint32 CreateDisposition, uint32 CreateOptions)
|
static void disk_file_set_fullpath(DISK_FILE* file, char* fullpath)
|
||||||
|
{
|
||||||
|
xfree(file->fullpath);
|
||||||
|
file->fullpath = fullpath;
|
||||||
|
file->filename = strrchr(file->fullpath, '/');
|
||||||
|
if (file->filename == NULL)
|
||||||
|
file->filename = file->fullpath;
|
||||||
|
else
|
||||||
|
file->filename += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean disk_file_init(DISK_FILE* file, uint32 DesiredAccess, uint32 CreateDisposition, uint32 CreateOptions)
|
||||||
{
|
{
|
||||||
const static int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
|
const static int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@ -184,7 +196,7 @@ boolean disk_file_init(DISK_FILE* file, uint32 DesiredAccess, uint32 CreateDispo
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!exists && (CreateOptions & FILE_DELETE_ON_CLOSE))
|
if (!exists && (CreateOptions & FILE_DELETE_ON_CLOSE))
|
||||||
file->delete_pending = 1;
|
file->delete_pending = True;
|
||||||
|
|
||||||
if ((DesiredAccess & GENERIC_ALL)
|
if ((DesiredAccess & GENERIC_ALL)
|
||||||
|| (DesiredAccess & GENERIC_WRITE)
|
|| (DesiredAccess & GENERIC_WRITE)
|
||||||
@ -213,12 +225,7 @@ DISK_FILE* disk_file_new(const char* base_path, const char* path, uint32 id,
|
|||||||
|
|
||||||
file = xnew(DISK_FILE);
|
file = xnew(DISK_FILE);
|
||||||
file->id = id;
|
file->id = id;
|
||||||
file->fullpath = disk_file_get_fullpath(base_path, path);
|
disk_file_set_fullpath(file, disk_file_combine_fullpath(base_path, path));
|
||||||
file->filename = strrchr(file->fullpath, '/');
|
|
||||||
if (file->filename == NULL)
|
|
||||||
file->filename = file->fullpath;
|
|
||||||
else
|
|
||||||
file->filename += 1;
|
|
||||||
file->fd = -1;
|
file->fd = -1;
|
||||||
|
|
||||||
if (!disk_file_init(file, DesiredAccess, CreateDisposition, CreateOptions))
|
if (!disk_file_init(file, DesiredAccess, CreateDisposition, CreateOptions))
|
||||||
@ -345,6 +352,100 @@ boolean disk_file_query_information(DISK_FILE* file, uint32 FsInformationClass,
|
|||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean disk_file_set_information(DISK_FILE* file, uint32 FsInformationClass, uint32 Length, STREAM* input)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
struct timeval tv[2];
|
||||||
|
uint64 LastWriteTime;
|
||||||
|
uint32 FileAttributes;
|
||||||
|
mode_t m;
|
||||||
|
uint64 size;
|
||||||
|
uint32 FileNameLength;
|
||||||
|
UNICONV* uniconv;
|
||||||
|
char* s;
|
||||||
|
char* p;
|
||||||
|
char* fullpath;
|
||||||
|
|
||||||
|
switch (FsInformationClass)
|
||||||
|
{
|
||||||
|
case FileBasicInformation:
|
||||||
|
/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
|
||||||
|
stream_seek_uint64(input); /* CreationTime */
|
||||||
|
stream_seek_uint64(input); /* LastAccessTime */
|
||||||
|
stream_read_uint64(input, LastWriteTime);
|
||||||
|
stream_seek_uint64(input); /* ChangeTime */
|
||||||
|
stream_read_uint32(input, FileAttributes);
|
||||||
|
|
||||||
|
if (fstat(file->fd, &st) != 0)
|
||||||
|
return False;
|
||||||
|
tv[0].tv_sec = st.st_atime;
|
||||||
|
tv[0].tv_usec = 0;
|
||||||
|
tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime);
|
||||||
|
tv[1].tv_usec = 0;
|
||||||
|
futimes(file->fd, tv);
|
||||||
|
|
||||||
|
if (FileAttributes > 0)
|
||||||
|
{
|
||||||
|
m = st.st_mode;
|
||||||
|
if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
|
||||||
|
m |= S_IWUSR;
|
||||||
|
else
|
||||||
|
m &= ~S_IWUSR;
|
||||||
|
if (m != st.st_mode)
|
||||||
|
fchmod(file->fd, st.st_mode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileEndOfFileInformation:
|
||||||
|
/* http://msdn.microsoft.com/en-us/library/cc232067.aspx */
|
||||||
|
case FileAllocationInformation:
|
||||||
|
/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
|
||||||
|
stream_read_uint64(input, size);
|
||||||
|
ftruncate(file->fd, size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileDispositionInformation:
|
||||||
|
/* http://msdn.microsoft.com/en-us/library/cc232098.aspx */
|
||||||
|
stream_read_uint8(input, file->delete_pending);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileRenameInformation:
|
||||||
|
/* http://msdn.microsoft.com/en-us/library/cc232085.aspx */
|
||||||
|
stream_seek_uint8(input); /* ReplaceIfExists */
|
||||||
|
stream_seek_uint8(input); /* RootDirectory */
|
||||||
|
stream_read_uint32(input, FileNameLength);
|
||||||
|
uniconv = freerdp_uniconv_new();
|
||||||
|
s = freerdp_uniconv_in(uniconv, stream_get_tail(input), FileNameLength);
|
||||||
|
freerdp_uniconv_free(uniconv);
|
||||||
|
fullpath = xmalloc(strlen(file->fullpath) + strlen(s) + 2);
|
||||||
|
strcpy(fullpath, file->fullpath);
|
||||||
|
p = strrchr(fullpath, '/');
|
||||||
|
if (p == NULL)
|
||||||
|
p = fullpath;
|
||||||
|
else
|
||||||
|
p++;
|
||||||
|
strcpy(p, s);
|
||||||
|
xfree(s);
|
||||||
|
|
||||||
|
if (rename(file->fullpath, fullpath) == 0)
|
||||||
|
{
|
||||||
|
disk_file_set_fullpath(file, fullpath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free(fullpath);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
boolean disk_file_query_directory(DISK_FILE* file, uint32 FsInformationClass, uint8 InitialQuery,
|
boolean disk_file_query_directory(DISK_FILE* file, uint32 FsInformationClass, uint8 InitialQuery,
|
||||||
const char* path, STREAM* output)
|
const char* path, STREAM* output)
|
||||||
{
|
{
|
||||||
|
@ -45,6 +45,7 @@ boolean disk_file_seek(DISK_FILE* file, uint64 Offset);
|
|||||||
boolean disk_file_read(DISK_FILE* file, uint8* buffer, uint32* Length);
|
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_write(DISK_FILE* file, uint8* buffer, uint32 Length);
|
||||||
boolean disk_file_query_information(DISK_FILE* file, uint32 FsInformationClass, STREAM* output);
|
boolean disk_file_query_information(DISK_FILE* file, uint32 FsInformationClass, STREAM* output);
|
||||||
|
boolean disk_file_set_information(DISK_FILE* file, uint32 FsInformationClass, uint32 Length, STREAM* input);
|
||||||
boolean disk_file_query_directory(DISK_FILE* file, uint32 FsInformationClass, uint8 InitialQuery,
|
boolean disk_file_query_directory(DISK_FILE* file, uint32 FsInformationClass, uint8 InitialQuery,
|
||||||
const char* path, STREAM* output);
|
const char* path, STREAM* output);
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ static void disk_process_irp_close(DISK_DEVICE* disk, IRP* irp)
|
|||||||
disk_file_free(file);
|
disk_file_free(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_write(irp->output, "\0\0\0\0\0", 5); /* Padding(5) */
|
stream_write_zero(irp->output, 5); /* Padding(5) */
|
||||||
|
|
||||||
irp->Complete(irp);
|
irp->Complete(irp);
|
||||||
}
|
}
|
||||||
@ -191,7 +191,7 @@ static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_SVC("read %u-%u from %s(%d).", Offset, Offset + Length, file->fullpath, file->id);
|
DEBUG_SVC("read %llu-%llu from %s(%d).", Offset, Offset + Length, file->fullpath, file->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +241,7 @@ static void disk_process_irp_write(DISK_DEVICE* disk, IRP* irp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_SVC("write %u-%u to %s(%d).", Offset, Offset + Length, file->fullpath, file->id);
|
DEBUG_SVC("write %llu-%llu to %s(%d).", Offset, Offset + Length, file->fullpath, file->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_write_uint32(irp->output, Length);
|
stream_write_uint32(irp->output, Length);
|
||||||
@ -269,16 +269,50 @@ static void disk_process_irp_query_information(DISK_DEVICE* disk, IRP* irp)
|
|||||||
{
|
{
|
||||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
DEBUG_WARN("query_information %s(%d) failed.", file->fullpath, file->id);
|
DEBUG_WARN("FsInformationClass %d on %s(%d) failed.", FsInformationClass, file->fullpath, file->id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_SVC("query_information %d on %s(%d).", FsInformationClass, file->fullpath, file->id);
|
DEBUG_SVC("FsInformationClass %d on %s(%d).", FsInformationClass, file->fullpath, file->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
irp->Complete(irp);
|
irp->Complete(irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void disk_process_irp_set_information(DISK_DEVICE* disk, IRP* irp)
|
||||||
|
{
|
||||||
|
DISK_FILE* file;
|
||||||
|
uint32 FsInformationClass;
|
||||||
|
uint32 Length;
|
||||||
|
|
||||||
|
stream_read_uint32(irp->input, FsInformationClass);
|
||||||
|
stream_read_uint32(irp->input, Length);
|
||||||
|
stream_seek(irp->input, 24); /* Padding */
|
||||||
|
|
||||||
|
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_set_information(file, FsInformationClass, Length, irp->input))
|
||||||
|
{
|
||||||
|
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
DEBUG_WARN("FsInformationClass %d on %s(%d) failed.", FsInformationClass, file->fullpath, file->id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUG_SVC("FsInformationClass %d on %s(%d) ok.", FsInformationClass, file->fullpath, file->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_write_uint32(irp->output, Length);
|
||||||
|
|
||||||
|
irp->Complete(irp);
|
||||||
|
}
|
||||||
|
|
||||||
static void disk_process_irp_query_volume_information(DISK_DEVICE* disk, IRP* irp)
|
static void disk_process_irp_query_volume_information(DISK_DEVICE* disk, IRP* irp)
|
||||||
{
|
{
|
||||||
uint32 FsInformationClass;
|
uint32 FsInformationClass;
|
||||||
@ -409,6 +443,12 @@ static void disk_process_irp_directory_control(DISK_DEVICE* disk, IRP* irp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void disk_process_irp_device_control(DISK_DEVICE* disk, IRP* irp)
|
||||||
|
{
|
||||||
|
stream_write_uint32(irp->output, 0); /* OutputBufferLength */
|
||||||
|
irp->Complete(irp);
|
||||||
|
}
|
||||||
|
|
||||||
static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
|
static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
|
||||||
{
|
{
|
||||||
switch (irp->MajorFunction)
|
switch (irp->MajorFunction)
|
||||||
@ -433,6 +473,10 @@ static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
|
|||||||
disk_process_irp_query_information(disk, irp);
|
disk_process_irp_query_information(disk, irp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IRP_MJ_SET_INFORMATION:
|
||||||
|
disk_process_irp_set_information(disk, irp);
|
||||||
|
break;
|
||||||
|
|
||||||
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
||||||
disk_process_irp_query_volume_information(disk, irp);
|
disk_process_irp_query_volume_information(disk, irp);
|
||||||
break;
|
break;
|
||||||
@ -441,6 +485,10 @@ static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
|
|||||||
disk_process_irp_directory_control(disk, irp);
|
disk_process_irp_directory_control(disk, irp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IRP_MJ_DEVICE_CONTROL:
|
||||||
|
disk_process_irp_device_control(disk, irp);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
|
DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
|
||||||
irp->IoStatus = STATUS_NOT_SUPPORTED;
|
irp->IoStatus = STATUS_NOT_SUPPORTED;
|
||||||
|
Loading…
Reference in New Issue
Block a user