www.pudn.com > vdksrc.zip > vdkntddk.c
/*
vdkntddk.c
VDK Kernel mode driver utility routines
Copyright (C) 2003 Ken Kato
*/
#include "vdkbase.h"
#include "vdkutil.h"
//
// Opens an image file
//
VDKSTAT
VdkOpenFile(
IN HANDLE *FileHandle,
IN PCHAR FileName,
IN ULONG NameLen,
IN ULONG ReadOnly)
{
CHAR buf[MAXIMUM_FILENAME_LENGTH];
ULONG prefix;
ANSI_STRING ansi_name;
UNICODE_STRING unicode_name;
OBJECT_ATTRIBUTES attributes;
IO_STATUS_BLOCK io_status;
VDKSTAT status = VDK_OK;
//
// append appropriate prefix
//
prefix = 0;
if (RtlCompareMemory(FileName, "\\??\\", 4) != 4) {
RtlCopyMemory(buf, "\\??\\", 4);
prefix = 4;
if ((*FileName == '\\' || *FileName == '/') &&
(*(FileName + 1) == '\\' || *(FileName + 1) == '/')) {
//
// UNC path
//
RtlCopyMemory(buf + prefix, "UNC", 3);
FileName++;
NameLen--;
prefix += 3;
}
}
RtlCopyMemory(buf + prefix, FileName, NameLen);
buf[NameLen + prefix] = '\0';
VDKTRACE(VDKOPEN | VDKINFO,
("[VDK] Opening file %s for %s\n",
buf, ReadOnly ? "read-only" : "read-write"));
//
// generate unicode filename
//
RtlInitAnsiString(&ansi_name, buf);
status = RtlAnsiStringToUnicodeString(
&unicode_name, &ansi_name, TRUE);
if (!VDKSUCCESS(status)) {
VDKTRACE(VDKOPEN,
("[VDK] Failed to convert filename to UNICODE\n"));
return status;
}
//
// open the file
//
InitializeObjectAttributes(
&attributes,
&unicode_name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = ZwCreateFile(
FileHandle,
ReadOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
&attributes,
&io_status,
NULL,
FILE_ATTRIBUTE_NORMAL,
ReadOnly ? FILE_SHARE_READ : 0,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE |
FILE_RANDOM_ACCESS |
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
RtlFreeUnicodeString(&unicode_name);
if (!VDKSUCCESS(status)) {
VDKTRACE(VDKOPEN,
("[VDK] ZwCreateFile - %s\n",
VdkStatusStr(status)));
*FileHandle = NULL;
}
return status;
}
//
// Check file attribute
//
VDKSTAT VdkCheckAttribute(
HANDLE FileHandle)
{
IO_STATUS_BLOCK io_status;
VDKSTAT status;
FILE_BASIC_INFORMATION file_basic;
//
// The NT cache manager can deadlock if a filesystem that is using
// the cache manager is used in a virtual disk that stores its file
// on a filesystem that is also using the cache manager, this is why
// we open the file with FILE_NO_INTERMEDIATE_BUFFERING above, however
// if the file is compressed or encrypted NT will not honor this
// request and cache it anyway since it need to store the
// decompressed/unencrypted data somewhere, therefor we put an extra
// check here and don't alow disk images to be compressed/encrypted.
//
status = ZwQueryInformationFile(
FileHandle,
&io_status,
&file_basic,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
if (!VDKSUCCESS(status)) {
VDKTRACE(VDKOPEN,
("[VDK] ZwQueryInformationFile - FILE_BASIC_INFORMATION %s\n",
VdkStatusStr(status)));
return status;
}
if (file_basic.FileAttributes & VDK_INVALID_ATTRIBUTES) {
VDKTRACE(VDKOPEN,("[VDK] File is compressed and/or encrypted\n"));
return STATUS_ACCESS_DENIED;
}
return STATUS_SUCCESS;
}
//
// Get actual file size
//
VDKSTAT VdkGetFileSize(
HANDLE FileHandle,
PINT64 FileSize)
{
IO_STATUS_BLOCK io_status;
VDKSTAT status;
FILE_STANDARD_INFORMATION file_standard;
status = ZwQueryInformationFile(
FileHandle,
&io_status,
&file_standard,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
if (!VDKSUCCESS(status)) {
VDKTRACE(VDKOPEN,
("[VDK] ZwQueryInformationFile - FILE_STANDARD_INFORMATION %s\n",
VdkStatusStr(status)));
return status;
}
*FileSize = file_standard.EndOfFile.QuadPart;
return status;
}
//
// Change actual file size
//
VDKSTAT VdkSetFileSize(
HANDLE FileHandle,
INT64 FileSize)
{
FILE_END_OF_FILE_INFORMATION end_of_file;
IO_STATUS_BLOCK io_status;
NTSTATUS status;
end_of_file.EndOfFile.QuadPart = FileSize;
status = ZwSetInformationFile(
FileHandle,
&io_status,
&end_of_file,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation);
if (!NT_SUCCESS(status)) {
VDKTRACE(VDKWRITE,
("[VDK] ZwSetInformationFile %s\n",
VdkStatusStr(status)));
}
return status;
}
//
// Write to file at specified offset
//
VDKSTAT VdkWriteFileAt(
HANDLE FileHandle,
INT64 Offset,
PVOID Buffer,
ULONG Length,
PULONG Result)
{
LARGE_INTEGER loffset;
IO_STATUS_BLOCK io_status;
NTSTATUS status;
loffset.QuadPart = Offset;
status = ZwWriteFile(
FileHandle,
NULL,
NULL,
NULL,
&io_status,
Buffer,
Length,
&loffset,
NULL);
if (!NT_SUCCESS(status)) {
VDKTRACE(VDKWRITE,
("[VDK] ZwWriteFile %s\n", VdkStatusStr(status)));
}
if (Result) {
*Result = io_status.Information;
}
return status;
}
//
// Read from file at specified offset
//
VDKSTAT VdkReadFileAt(
HANDLE FileHandle,
INT64 Offset,
PVOID Buffer,
ULONG Length,
PULONG Result)
{
LARGE_INTEGER loffset;
IO_STATUS_BLOCK io_status;
NTSTATUS status;
loffset.QuadPart = Offset;
status = ZwReadFile(
FileHandle,
NULL,
NULL,
NULL,
&io_status,
Buffer,
Length,
Offset == -1 ? NULL : &loffset,
NULL);
if (!NT_SUCCESS(status)) {
VDKTRACE(VDKREAD,
("[VDK] ZwReadFile %s\n", VdkStatusStr(status)));
}
if (Result) {
*Result = io_status.Information;
}
return status;
}