📄 vdkopen.c
字号:
/* vdkopen.c Virtual Disk open functions Copyright (C) 2003 Ken Kato*/#include "vdkbase.h"#include "vdkutil.h"#include "vdkfile.h"#include "vdkaccess.h"#include "cowdisk.h"#include "vmdisk.h"//// local functions//static VDKSTAT VdkSetCowdParam( PVDK_FILE_INFO DiskInfo, ULONG ReadOnly);static VDKSTAT VdkSetVmdkParam( PVDK_FILE_INFO DiskInfo, ULONG ReadOnly);//// declare pageable functions//#ifdef ALLOC_PRAGMA#pragma alloc_text(PAGE, VdkOpenCheckParam)#pragma alloc_text(PAGE, VdkOpenDisk)#pragma alloc_text(PAGE, VdkSetCowdParam)#pragma alloc_text(PAGE, VdkSetVmdkParam)#endif // ALLOC_PRAGMA//// Check open file info integrity//VDKSTAT VdkOpenCheckParam( PVDK_OPEN_FILE_INFO OpenInfo, ULONG InputLen){ ULONG fixed_size; ULONG total_sectors; ULONG total_name_len; ULONG generation; ULONG idx; // // check minimum length // if (InputLen < sizeof(VDK_OPEN_FILE_INFO)) { return VDK_BUFFER; } // // check DiskType // if (OpenInfo->DiskType != VDK_DISKTYPE_WRITABLE && OpenInfo->DiskType != VDK_DISKTYPE_READONLY && OpenInfo->DiskType != VDK_DISKTYPE_WRITEBLOCK) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: Invalid DiskType %u\n", OpenInfo->DiskType)); return VDK_PARAM; } // // There must be at least one file to open // if (OpenInfo->FilesTotal == 0 || OpenInfo->Capacity == 0) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: disk size == 0\n")); return VDK_PARAM; } // // If geometry values are specified, they must be // consistent with the number of total sectors // if (OpenInfo->Cylinders * OpenInfo->Tracks * OpenInfo->Sectors > OpenInfo->Capacity) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: geometry / capacity conflict\n")); return VDK_PARAM; } // // Calculate the minimum necessary size for // the VDK_OEPN_DISK and all VDK_OPEN_FILE_ITEM structures. // fixed_size = FIELD_OFFSET(VDK_OPEN_FILE_INFO, Files) + (sizeof(VDK_OPEN_FILE_ITEM) * OpenInfo->FilesTotal); // // Recheck input parameter length // -- large enough to contain all fixed info? // if (InputLen < fixed_size) { return VDK_BUFFER; } // // Check each file info // total_sectors = 0; total_name_len = 0; generation = 0; idx = 0; do { PVDK_OPEN_FILE_ITEM open_file; // // file item to work with // open_file = &(OpenInfo->Files[idx]); // // check file type // if (open_file->FileType != VDK_FILETYPE_NONE && open_file->FileType != VDK_FILETYPE_FLAT && open_file->FileType != VDK_FILETYPE_COWD && open_file->FileType != VDK_FILETYPE_VMDK) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: File #%u Invalid FileType %u\n", idx, open_file->FileType)); return VDK_PARAM; } // // Top level files cannot be missing if disk is writable // if (!generation && OpenInfo->DiskType == VDK_DISKTYPE_WRITABLE && open_file->FileType == VDK_FILETYPE_NONE) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: Missing top level file #%u\n", idx)); return VDK_PARAM; } // // check file length // if (open_file->Capacity == 0 || open_file->Capacity > OpenInfo->Capacity) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: File #%u invalid size %u\n", idx, open_file->Capacity)); return VDK_PARAM; } // // if the file is not missing, file name must be provided // if (open_file->FileType != VDK_FILETYPE_NONE && open_file->NameLength == 0) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: File #%u filename required\n", idx)); return VDK_PARAM; } // // BackOffset can only be used for solid files // if (open_file->FileType != VDK_FILETYPE_FLAT && open_file->BackOffset != 0) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: File #%u BackOffset #%lu\n", idx, open_file->BackOffset)); return VDK_PARAM; } // // Sum up the file length and name length // total_sectors += open_file->Capacity; total_name_len += open_file->NameLength; // // completed one generation? // if (total_sectors == OpenInfo->Capacity) { // // prepare for the next generation // generation++; total_sectors = 0; } else if (total_sectors > OpenInfo->Capacity) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: Size mismatch at File #%u\n", idx)); return VDK_PARAM; } } while (++idx < OpenInfo->FilesTotal); // // The last generation is complete? // if (total_sectors) { VDKTRACE(VDKOPEN, ("[VDK] IOCTL_VDK_OPEN_FILE: Size mismatch at File #%u\n", idx - 1)); return VDK_PARAM; } // // now total name length is known, check buffer length again // if (InputLen < fixed_size + total_name_len) { return VDK_BUFFER; } return VDK_OK;}//// Open image file(s)//VDKSTAT VdkOpenDisk( PVDK_OPEN_FILE_INFO OpenFile, PVDK_DISK_INFO DiskInfo){ PCHAR name_top; ULONG name_total; ULONG start_sector; ULONG generation; ULONG read_only; ULONG idx; VDKSTAT status = VDK_OK; // // store disk information // VdkZeroMem(DiskInfo, sizeof(VDK_DISK_INFO)); DiskInfo->DiskType = OpenFile->DiskType; DiskInfo->Capacity = OpenFile->Capacity; if (OpenFile->Cylinders && OpenFile->Tracks && OpenFile->Sectors) { DiskInfo->Cylinders = OpenFile->Cylinders; DiskInfo->Tracks = OpenFile->Tracks; DiskInfo->Sectors = OpenFile->Sectors; } else { // // make up suitable values // DiskInfo->Sectors = VDK_SECTORS_PER_TRACK; DiskInfo->Tracks = VDK_TRACKS_PER_CYLINDER; DiskInfo->Cylinders = OpenFile->Capacity / VDK_SECTORS_PER_TRACK / VDK_TRACKS_PER_CYLINDER; } DiskInfo->FilesTotal = OpenFile->FilesTotal; // // allocate buffer to store file information // DiskInfo->Files = (PVDK_FILE_INFO)VdkAllocMem( sizeof(VDK_FILE_INFO) * OpenFile->FilesTotal); if (!DiskInfo->Files) { VDKTRACE(VDKOPEN, ("[VDK] Can't allocate memory for disk info\n")); status = VDK_NOMEMORY; goto cleanup_exit; } VdkZeroMem(DiskInfo->Files, sizeof(VDK_FILE_INFO) * OpenFile->FilesTotal); // // process each files // name_top = (PCHAR)OpenFile + FIELD_OFFSET(VDK_OPEN_FILE_INFO, Files) + (sizeof(VDK_OPEN_FILE_ITEM) * OpenFile->FilesTotal); name_total = 0; start_sector = 0; generation = 0; read_only = (OpenFile->DiskType != VDK_DISKTYPE_WRITABLE); for (idx = 0; idx < DiskInfo->FilesTotal; idx++) { PVDK_FILE_INFO file_info = &DiskInfo->Files[idx]; // // set up basic parameters // file_info->FileType = OpenFile->Files[idx].FileType; file_info->Capacity = OpenFile->Files[idx].Capacity; file_info->NameLength = OpenFile->Files[idx].NameLength; file_info->StartSector = start_sector; // // skip "Missing" files // if (file_info->FileType == VDK_FILETYPE_NONE) { goto next_file; } // // open file // status = VdkOpenFile( &(file_info->FileHandle), name_top + name_total, file_info->NameLength, read_only); if (!VDKSUCCESS(status)) { goto cleanup_exit; } // // check file attributes // status = VdkCheckAttribute( file_info->FileHandle); if (!VDKSUCCESS(status)) { goto cleanup_exit; } // // get file size // { INT64 size; status = VdkGetFileSize(file_info->FileHandle, &size); if (!VDKSUCCESS(status)) { goto cleanup_exit; } file_info->EndOfFile = (ULONG)(size >> VDK_BYTE_SHIFT_TO_SECTOR); } // // prepare type specific parameters // if (file_info->FileType == VDK_FILETYPE_FLAT) { file_info->prm.SolidBackOffset = OpenFile->Files[idx].BackOffset; VDKTRACE(VDKOPEN | VDKINFO, ("[VDK] BackOffset = %lu\n", file_info->prm.SolidBackOffset)); } else if (file_info->FileType == VDK_FILETYPE_COWD) { status = VdkSetCowdParam(file_info, read_only); if (!VDKSUCCESS(status)) { goto cleanup_exit; } } else if (file_info->FileType == VDK_FILETYPE_VMDK) { status = VdkSetVmdkParam(file_info, read_only); if (!VDKSUCCESS(status)) { goto cleanup_exit; } }next_file: VDKTRACE(VDKOPEN | VDKINFO, ("[VDK] FileType = %lu\n", file_info->FileType)); VDKTRACE(VDKOPEN | VDKINFO, ("[VDK] StartSector = %lu\n", file_info->StartSector)); VDKTRACE(VDKOPEN | VDKINFO, ("[VDK] Capacity = %lu\n", file_info->Capacity)); VDKTRACE(VDKOPEN | VDKINFO, ("[VDK] EndOfFile = %lu\n", file_info->EndOfFile)); // // calculate next file's start sector // start_sector += file_info->Capacity; // // sum up name length // name_total += file_info->NameLength; // // completed one generation? // if (start_sector == OpenFile->Capacity) { start_sector = 0; generation++; read_only = TRUE; } } // next file // // Store filenames // DiskInfo->NameBuffer = VdkAllocMem(name_total); if (!DiskInfo->NameBuffer) { VDKTRACE(VDKOPEN, ("[VDK] Can't allocate memory for image path\n")); status = VDK_NOMEMORY; goto cleanup_exit; } DiskInfo->BufferLen = name_total; VdkCopyMem(DiskInfo->NameBuffer, name_top, name_total);cleanup_exit: if (!VDKSUCCESS(status)) { VdkCloseDisk(DiskInfo); } return status;}//// Prepare extra parameters for COWD//VDKSTAT VdkSetCowdParam( PVDK_FILE_INFO FileInfo, ULONG ReadOnly){ PVDK_COWD_PARAM cowd_prm = NULL; PCOWD_SECTOR_0 cowd_hdr = NULL; VDKSTAT status = VDK_OK; //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -