rdpdr/disk: add query directory irp processing.

This commit is contained in:
Vic Lee 2011-08-07 19:24:29 +08:00
parent 12215d0e0a
commit f598bca687
3 changed files with 189 additions and 9 deletions

View File

@ -23,7 +23,6 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fnmatch.h>
#include <utime.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/stream.h>
@ -247,7 +246,6 @@ void disk_file_free(DISK_FILE* file)
}
xfree(file->fullpath);
xfree(file->pattern);
xfree(file);
}
@ -309,26 +307,26 @@ boolean disk_file_query_information(DISK_FILE* file, uint32 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_uint32(output, 36); /* Length */
stream_check_size(output, 36);
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 */
/* Reserved(4), MUST NOT be added! */
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_uint32(output, 22); /* Length */
stream_check_size(output, 22);
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 */
/* Reserved(2), MUST NOT be added! */
break;
case FileAttributeTagInformation:
@ -346,3 +344,123 @@ boolean disk_file_query_information(DISK_FILE* file, uint32 FsInformationClass,
}
return True;
}
boolean disk_file_query_directory(DISK_FILE* file, uint32 FsInformationClass, uint8 InitialQuery,
const char* path, STREAM* output)
{
struct dirent* ent;
char* ent_path;
struct stat st;
UNICONV* uniconv;
size_t len;
boolean ret;
DEBUG_SVC("path %s FsInformationClass %d", path, FsInformationClass);
if (InitialQuery != 0)
{
rewinddir(file->dir);
}
ent = readdir(file->dir);
if (ent == NULL)
{
stream_write_uint32(output, 0); /* Length */
stream_write_uint8(output, 0); /* Padding */
return False;
}
memset(&st, 0, sizeof(struct stat));
ent_path = xmalloc(strlen(file->fullpath) + strlen(ent->d_name) + 2);
sprintf(ent_path, "%s/%s", file->fullpath, ent->d_name);
if (stat(ent_path, &st) != 0)
{
DEBUG_WARN("stat %s failed.", ent_path);
}
xfree(ent_path);
uniconv = freerdp_uniconv_new();
ent_path = freerdp_uniconv_out(uniconv, ent->d_name, &len);
freerdp_uniconv_free(uniconv);
ret = True;
switch (FsInformationClass)
{
case FileDirectoryInformation:
/* http://msdn.microsoft.com/en-us/library/cc232097.aspx */
stream_write_uint32(output, 64 + len); /* Length */
stream_check_size(output, 64 + len);
stream_write_uint32(output, 0); /* NextEntryOffset */
stream_write_uint32(output, 0); /* FileIndex */
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_uint64(output, st.st_size); /* EndOfFile */
stream_write_uint64(output, st.st_size); /* AllocationSize */
stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
stream_write_uint32(output, len); /* FileNameLength */
stream_write(output, ent_path, len);
break;
case FileFullDirectoryInformation:
/* http://msdn.microsoft.com/en-us/library/cc232068.aspx */
stream_write_uint32(output, 68 + len); /* Length */
stream_check_size(output, 68 + len);
stream_write_uint32(output, 0); /* NextEntryOffset */
stream_write_uint32(output, 0); /* FileIndex */
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_uint64(output, st.st_size); /* EndOfFile */
stream_write_uint64(output, st.st_size); /* AllocationSize */
stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
stream_write_uint32(output, len); /* FileNameLength */
stream_write_uint32(output, 0); /* EaSize */
stream_write(output, ent_path, len);
break;
case FileBothDirectoryInformation:
/* http://msdn.microsoft.com/en-us/library/cc232095.aspx */
stream_write_uint32(output, 93 + len); /* Length */
stream_check_size(output, 93 + len);
stream_write_uint32(output, 0); /* NextEntryOffset */
stream_write_uint32(output, 0); /* FileIndex */
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_uint64(output, st.st_size); /* EndOfFile */
stream_write_uint64(output, st.st_size); /* AllocationSize */
stream_write_uint32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
stream_write_uint32(output, len); /* FileNameLength */
stream_write_uint32(output, 0); /* EaSize */
stream_write_uint8(output, 0); /* ShortNameLength */
/* Reserved(1), MUST NOT be added! */
stream_write_zero(output, 24); /* ShortName */
stream_write(output, ent_path, len);
break;
case FileNamesInformation:
/* http://msdn.microsoft.com/en-us/library/cc232077.aspx */
stream_write_uint32(output, 12 + len); /* Length */
stream_check_size(output, 12 + len);
stream_write_uint32(output, 0); /* NextEntryOffset */
stream_write_uint32(output, 0); /* FileIndex */
stream_write_uint32(output, len); /* FileNameLength */
stream_write(output, ent_path, len);
break;
default:
stream_write_uint32(output, 0); /* Length */
stream_write_uint8(output, 0); /* Padding */
DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
ret = False;
break;
}
xfree(ent_path);
return ret;
}

View File

@ -34,7 +34,6 @@ struct _DISK_FILE
DIR* dir;
char* fullpath;
char* filename;
char* pattern;
boolean delete_pending;
};
@ -46,5 +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_write(DISK_FILE* file, uint8* buffer, uint32 Length);
boolean disk_file_query_information(DISK_FILE* file, uint32 FsInformationClass, STREAM* output);
boolean disk_file_query_directory(DISK_FILE* file, uint32 FsInformationClass, uint8 InitialQuery,
const char* path, STREAM* output);
#endif /* __DISK_FILE_H */

View File

@ -352,6 +352,63 @@ static void disk_process_irp_query_volume_information(DISK_DEVICE* disk, IRP* ir
irp->Complete(irp);
}
static void disk_process_irp_query_directory(DISK_DEVICE* disk, IRP* irp)
{
DISK_FILE* file;
uint32 FsInformationClass;
uint8 InitialQuery;
uint32 PathLength;
UNICONV* uniconv;
char* path;
stream_read_uint32(irp->input, FsInformationClass);
stream_read_uint8(irp->input, InitialQuery);
stream_read_uint32(irp->input, PathLength);
stream_seek(irp->input, 23); /* Padding */
uniconv = freerdp_uniconv_new();
path = freerdp_uniconv_in(uniconv, stream_get_tail(irp->input), PathLength);
freerdp_uniconv_free(uniconv);
file = disk_get_file_by_id(disk, irp->FileId);
if (file == NULL)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
stream_write_uint32(irp->output, 0); /* Length */
DEBUG_WARN("FileId %d not valid.", irp->FileId);
}
else if (!disk_file_query_directory(file, FsInformationClass, InitialQuery, path, irp->output))
{
irp->IoStatus = STATUS_NO_MORE_FILES;
}
xfree(path);
irp->Complete(irp);
}
static void disk_process_irp_directory_control(DISK_DEVICE* disk, IRP* irp)
{
switch (irp->MinorFunction)
{
case IRP_MN_QUERY_DIRECTORY:
disk_process_irp_query_directory(disk, irp);
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY: /* TODO */
irp->Discard(irp);
break;
default:
DEBUG_WARN("MinorFunction 0x%X not supported", irp->MinorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;
stream_write_uint32(irp->output, 0); /* Length */
irp->Complete(irp);
break;
}
}
static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
{
switch (irp->MajorFunction)
@ -380,6 +437,10 @@ static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
disk_process_irp_query_volume_information(disk, irp);
break;
case IRP_MJ_DIRECTORY_CONTROL:
disk_process_irp_directory_control(disk, irp);
break;
default:
DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;