⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32_io.c

📁 添加linux下对NTFS格式文件系统访问支持的源代码ntfs-3g
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * win32_io.c - A stdio-like disk I/O implementation for low-level disk access *		on Win32.  Can access an NTFS volume while it is mounted. *		Originated from the Linux-NTFS project. * * Copyright (c) 2003-2004 Lode Leroy * Copyright (c) 2003-2006 Anton Altaparmakov * Copyright (c) 2004-2005 Yuval Fledel * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program/include file is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (in the main directory of the NTFS-3G * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "config.h"#ifdef HAVE_WINDOWS_H#include <windows.h>#endif#include <winioctl.h>#ifdef HAVE_STDIO_H#include <stdio.h>#endif#ifdef HAVE_CTYPE_H#include <ctype.h>#endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif/* Prevent volume.h from being be loaded, as it conflicts with winnt.h. */#define _NTFS_VOLUME_Hstruct ntfs_volume;typedef struct ntfs_volume ntfs_volume;#include "debug.h"#include "types.h"#include "device.h"#ifndef NTFS_BLOCK_SIZE#define NTFS_BLOCK_SIZE		512#define NTFS_BLOCK_SIZE_BITS	9#endif#ifndef IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 5636096#endif/* Windows 2k+ imports. */typedef HANDLE (WINAPI *LPFN_FINDFIRSTVOLUME)(LPTSTR, DWORD);typedef BOOL (WINAPI *LPFN_FINDNEXTVOLUME)(HANDLE, LPTSTR, DWORD);typedef BOOL (WINAPI *LPFN_FINDVOLUMECLOSE)(HANDLE);typedef BOOL (WINAPI *LPFN_SETFILEPOINTEREX)(HANDLE, LARGE_INTEGER,		PLARGE_INTEGER, DWORD);static LPFN_FINDFIRSTVOLUME fnFindFirstVolume = NULL;static LPFN_FINDNEXTVOLUME fnFindNextVolume = NULL;static LPFN_FINDVOLUMECLOSE fnFindVolumeClose = NULL;static LPFN_SETFILEPOINTEREX fnSetFilePointerEx = NULL;#ifdef UNICODE#define FNPOSTFIX "W"#else#define FNPOSTFIX "A"#endif/** * struct win32_fd - */typedef struct {	HANDLE handle;	s64 pos;		/* Logical current position on the volume. */	s64 part_start;	s64 part_length;	int part_hidden_sectors;	s64 geo_size, geo_cylinders;	DWORD geo_sectors, geo_heads;	HANDLE vol_handle;} win32_fd;/** * ntfs_w32error_to_errno - convert a win32 error code to the unix one * @w32error:	the win32 error code * * Limited to a relatively small but useful number of codes. */static int ntfs_w32error_to_errno(unsigned int w32error){	ntfs_log_trace("Converting w32error 0x%x.\n",w32error);	switch (w32error) {		case ERROR_INVALID_FUNCTION:			return EBADRQC;		case ERROR_FILE_NOT_FOUND:		case ERROR_PATH_NOT_FOUND:		case ERROR_INVALID_NAME:			return ENOENT;		case ERROR_TOO_MANY_OPEN_FILES:			return EMFILE;		case ERROR_ACCESS_DENIED:			return EACCES;		case ERROR_INVALID_HANDLE:			return EBADF;		case ERROR_NOT_ENOUGH_MEMORY:			return ENOMEM;		case ERROR_OUTOFMEMORY:			return ENOSPC;		case ERROR_INVALID_DRIVE:		case ERROR_BAD_UNIT:			return ENODEV;		case ERROR_WRITE_PROTECT:			return EROFS;		case ERROR_NOT_READY:		case ERROR_SHARING_VIOLATION:			return EBUSY;		case ERROR_BAD_COMMAND:			return EINVAL;		case ERROR_SEEK:		case ERROR_NEGATIVE_SEEK:			return ESPIPE;		case ERROR_NOT_SUPPORTED:			return EOPNOTSUPP;		case ERROR_BAD_NETPATH:			return ENOSHARE;		default:			/* generic message */			return ENOMSG;	}}/** * libntfs_SetFilePointerEx - emulation for SetFilePointerEx() * * We use this to emulate SetFilePointerEx() when it is not present.  This can * happen since SetFilePointerEx() only exists in Win2k+. */static BOOL WINAPI libntfs_SetFilePointerEx(HANDLE hFile,		LARGE_INTEGER liDistanceToMove,		PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod){	liDistanceToMove.LowPart = SetFilePointer(hFile,			liDistanceToMove.LowPart, &liDistanceToMove.HighPart,			dwMoveMethod);	if (liDistanceToMove.LowPart == INVALID_SET_FILE_POINTER &&			GetLastError() != NO_ERROR) {		if (lpNewFilePointer)			lpNewFilePointer->QuadPart = -1;		return FALSE;	}	if (lpNewFilePointer)		lpNewFilePointer->QuadPart = liDistanceToMove.QuadPart;	return TRUE;}/** * ntfs_device_win32_init_imports - initialize the function pointers * * The Find*Volume and SetFilePointerEx functions exist only on win2k+, as such * we cannot just staticly import them. * * This function initializes the imports if the functions do exist and in the * SetFilePointerEx case, we emulate the function ourselves if it is not * present. * * Note: The values are cached, do be afraid to run it more than once. */static void ntfs_device_win32_init_imports(void){	HMODULE kernel32 = GetModuleHandle("kernel32");	if (!kernel32) {		errno = ntfs_w32error_to_errno(GetLastError());		ntfs_log_trace("kernel32.dll could not be imported.\n");	}	if (!fnSetFilePointerEx) {		if (kernel32)			fnSetFilePointerEx = (LPFN_SETFILEPOINTEREX)					GetProcAddress(kernel32,					"SetFilePointerEx");		/*		 * If we did not get kernel32.dll or it is not Win2k+, emulate		 * SetFilePointerEx().		 */		if (!fnSetFilePointerEx) {			ntfs_log_debug("SetFilePonterEx() not found in "					"kernel32.dll: Enabling emulation.\n");			fnSetFilePointerEx = libntfs_SetFilePointerEx;		}	}	/* Cannot do lookups if we could not get kernel32.dll... */	if (!kernel32)		return;	if (!fnFindFirstVolume)		fnFindFirstVolume = (LPFN_FINDFIRSTVOLUME)				GetProcAddress(kernel32, "FindFirstVolume"				FNPOSTFIX);	if (!fnFindNextVolume)		fnFindNextVolume = (LPFN_FINDNEXTVOLUME)				GetProcAddress(kernel32, "FindNextVolume"				FNPOSTFIX);	if (!fnFindVolumeClose)		fnFindVolumeClose = (LPFN_FINDVOLUMECLOSE)				GetProcAddress(kernel32, "FindVolumeClose");}/** * ntfs_device_unix_status_flags_to_win32 - convert unix->win32 open flags * @flags:	unix open status flags * * Supported flags are O_RDONLY, O_WRONLY and O_RDWR. */static __inline__ int ntfs_device_unix_status_flags_to_win32(int flags){	int win_mode;	switch (flags & O_ACCMODE) {	case O_RDONLY:		win_mode = FILE_READ_DATA;		break;	case O_WRONLY:		win_mode = FILE_WRITE_DATA;		break;	case O_RDWR:		win_mode = FILE_READ_DATA | FILE_WRITE_DATA;		break;	default:		/* error */		ntfs_log_trace("Unknown status flags.\n");		win_mode = 0;	}	return win_mode;}/** * ntfs_device_win32_simple_open_file - just open a file via win32 API * @filename:	name of the file to open * @handle:	pointer the a HANDLE in which to put the result * @flags:	unix open status flags * @locking:	will the function gain an exclusive lock on the file? * * Supported flags are O_RDONLY, O_WRONLY and O_RDWR. * * Return 0 if o.k. *	 -1 if not, and errno set.  In this case handle is trashed. */static int ntfs_device_win32_simple_open_file(const char *filename,		HANDLE *handle, int flags, BOOL locking){	*handle = CreateFile(filename,			ntfs_device_unix_status_flags_to_win32(flags),			locking ? 0 : (FILE_SHARE_WRITE | FILE_SHARE_READ),			NULL, OPEN_EXISTING, 0, NULL);	if (*handle == INVALID_HANDLE_VALUE) {		errno = ntfs_w32error_to_errno(GetLastError());		ntfs_log_trace("CreateFile(%s) failed.\n", filename);		return -1;	}	return 0;}/** * ntfs_device_win32_lock - lock the volume * @handle:	a win32 HANDLE for a volume to lock * * Locking a volume means no one can access its contents. * Exiting the process automatically unlocks the volume, except in old NT4s. * * Return 0 if o.k. *	 -1 if not, and errno set. */static int ntfs_device_win32_lock(HANDLE handle){	DWORD i;	if (!DeviceIoControl(handle, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &i,			NULL)) {		errno = ntfs_w32error_to_errno(GetLastError());		ntfs_log_trace("Couldn't lock volume.\n");		return -1;	}	ntfs_log_debug("Volume locked.\n");	return 0;}/** * ntfs_device_win32_unlock - unlock the volume * @handle:	the win32 HANDLE which the volume was locked with * * Return 0 if o.k. *	 -1 if not, and errno set. */static int ntfs_device_win32_unlock(HANDLE handle){	DWORD i;	if (!DeviceIoControl(handle, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &i,			NULL)) {		errno = ntfs_w32error_to_errno(GetLastError());		ntfs_log_trace("Couldn't unlock volume.\n");		return -1;	}	ntfs_log_debug("Volume unlocked.\n");	return 0;}/** * ntfs_device_win32_dismount - dismount a volume * @handle:	a win32 HANDLE for a volume to dismount * * Dismounting means the system will refresh the volume in the first change it * gets.  Usefull after altering the file structures. * The volume must be locked by the current process while dismounting. * A side effect is that the volume is also unlocked, but you must not rely om * this. * * Return 0 if o.k. *	 -1 if not, and errno set. */static int ntfs_device_win32_dismount(HANDLE handle){	DWORD i;	if (!DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0,			&i, NULL)) {		errno = ntfs_w32error_to_errno(GetLastError());		ntfs_log_trace("Couldn't dismount volume.\n");		return -1;	}	ntfs_log_debug("Volume dismounted.\n");	return 0;}/** * ntfs_device_win32_getsize - get file size via win32 API * @handle:	pointer the file HANDLE obtained via open * * Only works on ordinary files. * * Return The file size if o.k. *	 -1 if not, and errno set. */static s64 ntfs_device_win32_getsize(HANDLE handle){	DWORD loword, hiword;	loword = GetFileSize(handle, &hiword);	if (loword == INVALID_FILE_SIZE) {		errno = ntfs_w32error_to_errno(GetLastError());		ntfs_log_trace("Couldn't get file size.\n");		return -1;	}	return ((s64)hiword << 32) + loword;}/** * ntfs_device_win32_getdisklength - get disk size via win32 API * @handle:	pointer the file HANDLE obtained via open * @argp:	pointer to result buffer * * Only works on PhysicalDriveX type handles. * * Return The disk size if o.k. *	 -1 if not, and errno set. */static s64 ntfs_device_win32_getdisklength(HANDLE handle){	GET_LENGTH_INFORMATION buf;	DWORD i;	if (!DeviceIoControl(handle, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &buf,			sizeof(buf), &i, NULL)) {		errno = ntfs_w32error_to_errno(GetLastError());		ntfs_log_trace("Couldn't get disk length.\n");		return -1;	}	ntfs_log_debug("Disk length: %lld.\n", buf.Length.QuadPart);	return buf.Length.QuadPart;}/** * ntfs_device_win32_getntfssize - get NTFS volume size via win32 API * @handle:	pointer the file HANDLE obtained via open * @argp:	pointer to result buffer * * Only works on NTFS volume handles. * An annoying bug in windows is that an NTFS volume does not occupy the entire * partition, namely not the last sector (which holds the backup boot sector, * and normally not interesting). * Use this function to get the length of the accessible space through a given * volume handle. * * Return The volume size if o.k. *	 -1 if not, and errno set. */static s64 ntfs_device_win32_getntfssize(HANDLE handle){	s64 rvl;#ifdef FSCTL_GET_NTFS_VOLUME_DATA	DWORD i;	NTFS_VOLUME_DATA_BUFFER buf;	if (!DeviceIoControl(handle, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &buf,			sizeof(buf), &i, NULL)) {		errno = ntfs_w32error_to_errno(GetLastError());		ntfs_log_trace("Couldn't get NTFS volume length.\n");		return -1;	}	rvl = buf.NumberSectors.QuadPart * buf.BytesPerSector;	ntfs_log_debug("NTFS volume length: 0x%llx.\n", (long long)rvl);#else	errno = EINVAL;	rvl = -1;#endif	return rvl;}/** * ntfs_device_win32_getgeo - get CHS information of a drive * @handle:	an open handle to the PhysicalDevice * @fd:		a win_fd structure that will be filled * * Return 0 if o.k. *	 -1 if not, and errno  set. * * In Windows NT+: fills size, sectors, and cylinders and sets heads to -1. * In Windows XP+: fills size, sectors, cylinders, and heads. * * Note: In pre XP, this requires write permission, even though nothing is * actually written. * * If fails, sets sectors, cylinders, heads, and size to -1. */static int ntfs_device_win32_getgeo(HANDLE handle, win32_fd *fd){	DWORD i;	BOOL rvl;	BYTE b[sizeof(DISK_GEOMETRY) + sizeof(DISK_PARTITION_INFO) +			sizeof(DISK_DETECTION_INFO) + 512];	rvl = DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL,			0, &b, sizeof(b), &i, NULL);	if (rvl) {		ntfs_log_debug("GET_DRIVE_GEOMETRY_EX detected.\n");		DISK_DETECTION_INFO *ddi = (PDISK_DETECTION_INFO)				(((PBYTE)(&((PDISK_GEOMETRY_EX)b)->Data)) +				(((PDISK_PARTITION_INFO)				(&((PDISK_GEOMETRY_EX)b)->Data))->				SizeOfPartitionInfo));		fd->geo_cylinders = ((DISK_GEOMETRY*)&b)->Cylinders.QuadPart;		fd->geo_sectors = ((DISK_GEOMETRY*)&b)->SectorsPerTrack;		fd->geo_size = ((DISK_GEOMETRY_EX*)&b)->DiskSize.QuadPart;		switch (ddi->DetectionType) {		case DetectInt13:			fd->geo_cylinders = ddi->Int13.MaxCylinders;			fd->geo_sectors = ddi->Int13.SectorsPerTrack;			fd->geo_heads = ddi->Int13.MaxHeads;			return 0;		case DetectExInt13:			fd->geo_cylinders = ddi->ExInt13.ExCylinders;			fd->geo_sectors = ddi->ExInt13.ExSectorsPerTrack;			fd->geo_heads = ddi->ExInt13.ExHeads;			return 0;		case DetectNone:		default:			break;		}	} else		fd->geo_heads = -1;	rvl = DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,			&b, sizeof(b), &i, NULL);	if (rvl) {		ntfs_log_debug("GET_DRIVE_GEOMETRY detected.\n");		fd->geo_cylinders = ((DISK_GEOMETRY*)&b)->Cylinders.QuadPart;		fd->geo_sectors = ((DISK_GEOMETRY*)&b)->SectorsPerTrack;		fd->geo_size = fd->geo_cylinders * fd->geo_sectors *				((DISK_GEOMETRY*)&b)->TracksPerCylinder *				((DISK_GEOMETRY*)&b)->BytesPerSector;		return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -