基于visual c++之windows核心编程代码分析(24)IO控制、内核通信

我们在进行Windows编程的时候,经常需要进行IO控制与内核通信,我们来实现IO控制与内核通信。请见代码实现与注释讲解

 

驱动代码实现与分析

/* 头文件 */
#include <ntddk.h>// 包括了很多NT内核的类型、结构、函数定义,开发驱动时需要包括此头文件
#include <string.h>
#include "xioctl.h"
/* 常量与预定义 */
#define NT_DEVICE_NAME      L"\\Device\\XIOCTL"
#define DOS_DEVICE_NAME     L"\\DosDevices\\IoctlTest"

#if DBG
#define XIOCTL_KDPRINT(_x_) \
                DbgPrint("XIOCTL.SYS: ");\
                DbgPrint _x_;
#else
#define XIOCTL_KDPRINT(_x_)
#endif 

/* 函数声明 */
NTSTATUS DriverEntry(PDRIVER_OBJECT  DriverObject, PUNICODE_STRING RegistryPath);
NTSTATUS XioctlCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS XioctlDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp );
VOID XioctlUnloadDriver(PDRIVER_OBJECT DriverObject );
VOID PrintIrpInfo( PIRP Irp );
VOID PrintChars( PCHAR BufferAddress, ULONG CountChars );

#ifdef ALLOC_PRAGMA
#pragma alloc_text( INIT, DriverEntry )
#pragma alloc_text( PAGE, XioctlCreateClose)
#pragma alloc_text( PAGE, XioctlDeviceControl)
#pragma alloc_text( PAGE, XioctlUnloadDriver)
#pragma alloc_text( PAGE, PrintIrpInfo)
#pragma alloc_text( PAGE, PrintChars)
#endif // ALLOC_PRAGMA


/*************************************
* DriverEntry
* 功能	驱动的入口函数,分配了相关处理例程
**************************************/
NTSTATUS
DriverEntry(
    IN OUT PDRIVER_OBJECT   DriverObject,
    IN PUNICODE_STRING      RegistryPath
    )
{
    NTSTATUS        ntStatus;
    UNICODE_STRING  ntUnicodeString;    // 设备名
    UNICODE_STRING  ntWin32NameString;    // Win32 设备名
    PDEVICE_OBJECT  deviceObject = NULL;    // 设备对象


    RtlInitUnicodeString( &ntUnicodeString, NT_DEVICE_NAME );
    // 创建设备
    ntStatus = IoCreateDevice(
        DriverObject,                   // 驱动对象 DriverEntry 的参数
        0,                              // 不使用设备扩展
        &ntUnicodeString,               // 设备名 "\Device\XIOCTL"
        FILE_DEVICE_UNKNOWN,            // 设备类型
        FILE_DEVICE_SECURE_OPEN,   		  // 
        FALSE,                          // 
        &deviceObject );                // 设备对象

    if ( !NT_SUCCESS( ntStatus ) )
    {
        XIOCTL_KDPRINT(("Couldn't create the device object\n"));
        return ntStatus;
    }
    // 初始化处理例程
    DriverObject->MajorFunction[IRP_MJ_CREATE] = XioctlCreateClose;// 创建时会调用
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = XioctlCreateClose;// 关闭时会调用
    // 处理IO控制
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = XioctlDeviceControl;
    DriverObject->DriverUnload = XioctlUnloadDriver;// 卸载时会调用
   
    // WIN32 设备名
    RtlInitUnicodeString( &ntWin32NameString, DOS_DEVICE_NAME );

    // 在设备名和WIN32设备名之间创建符号连接
    ntStatus = IoCreateSymbolicLink(
                        &ntWin32NameString, &ntUnicodeString );

    if ( !NT_SUCCESS( ntStatus ) )
    {
        XIOCTL_KDPRINT(("Couldn't create symbolic link\n"));
        IoDeleteDevice( deviceObject );
    }

    return ntStatus;
}

/*************************************
* XioctlCreateClose
* 功能	驱动对象的处理例程,由DriverEntry指定
*				本函数中驱动对象在创建和关闭时调用的例程。
*				没有实际的功能,只是将状态设置为 成功
**************************************/
NTSTATUS
XioctlCreateClose(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    
    return STATUS_SUCCESS;
}

/*************************************
* XioctlUnloadDriver
* 功能	卸载驱动时调用的例程,
*       删除符号连接,删除设备
**************************************/
VOID
XioctlUnloadDriver(
    IN PDRIVER_OBJECT DriverObject
    )

{
    PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
    UNICODE_STRING uniWin32NameString;

    RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );


    // 删除符号连接    
    IoDeleteSymbolicLink( &uniWin32NameString );
    // 删除设备
    if ( deviceObject != NULL )
    {
        IoDeleteDevice( deviceObject );
    }
}

/*************************************
* XioctlDeviceControl
* 功能	处理IO控制的例程
**************************************/
NTSTATUS
XioctlDeviceControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    PIO_STACK_LOCATION  irpSp;// 当前栈的位置
    NTSTATUS            ntStatus = STATUS_SUCCESS;// 执行状态,成功\失败
    ULONG               inBufLength; // 输入缓存大小
    ULONG               outBufLength; // 输出缓存大小
    PCHAR               inBuf, outBuf; // 输入输出缓存
    PCHAR               data = "This String is from Device Driver !!!";
    ULONG               datalen = strlen(data)+1;//输出数据的长度
    PMDL                mdl = NULL;
    PCHAR               buffer = NULL;  

		// 处理IRP
    irpSp = IoGetCurrentIrpStackLocation( Irp );
    inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
    outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;

    if(!inBufLength || !outBufLength)
    {
        ntStatus = STATUS_INVALID_PARAMETER;
        goto End;
    }

    // 判断IOCTL
    switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
    {
    case IOCTL_XIOCTL_BUFFER: 
    		// 显示收到的IRP
        XIOCTL_KDPRINT(("Called IOCTL_SIOCTL_METHOD_BUFFERED\n")); 
        PrintIrpInfo(Irp);

        // 设备IN OUT 缓存
        inBuf = Irp->AssociatedIrp.SystemBuffer;
        outBuf = Irp->AssociatedIrp.SystemBuffer;

        // 从输入缓存中获得信息
        XIOCTL_KDPRINT(("\tData from User : %s", inBuf));
        // 复制数据到输出缓存
        strncpy(outBuf, data, outBufLength);
				// 打印输出输出缓存的内容
        XIOCTL_KDPRINT(("\tData to User : %s", outBuf));
        // 设置IRP 
        Irp->IoStatus.Information = (outBufLength<datalen?outBufLength:datalen);

       break;
		// 还可以定义其他IO 控制码
		
    default:

        // 处理其他示知的IO code
        ntStatus = STATUS_INVALID_DEVICE_REQUEST;
        XIOCTL_KDPRINT(("ERROR: unrecognized IOCTL %x\n",
            irpSp->Parameters.DeviceIoControl.IoControlCode));
        break;
    }

End:
    // 设备状态,完成IPR处理
    Irp->IoStatus.Status = ntStatus;
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    return ntStatus;
}

/*************************************
* PrintIrpInfo
* 功能	打印IPR信息
**************************************/
VOID
PrintIrpInfo(
    PIRP Irp)
{
    PIO_STACK_LOCATION  irpSp;
    irpSp = IoGetCurrentIrpStackLocation( Irp );

    XIOCTL_KDPRINT(("\tIrp->AssociatedIrp.SystemBuffer = 0x%p\n",
        Irp->AssociatedIrp.SystemBuffer)); 
    XIOCTL_KDPRINT(("\tIrp->UserBuffer = 0x%p\n", Irp->UserBuffer)); 
    XIOCTL_KDPRINT(("\tirpSp->Parameters.DeviceIoControl.Type3InputBuffer = 0x%p\n",
        irpSp->Parameters.DeviceIoControl.Type3InputBuffer)); 
    XIOCTL_KDPRINT(("\tirpSp->Parameters.DeviceIoControl.InputBufferLength = %d\n",
        irpSp->Parameters.DeviceIoControl.InputBufferLength)); 
    XIOCTL_KDPRINT(("\tirpSp->Parameters.DeviceIoControl.OutputBufferLength = %d\n",
        irpSp->Parameters.DeviceIoControl.OutputBufferLength )); 
    return;
}


实现加载与卸载驱动,

/* 头文件 */
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "..\sys\xioctl.h"
/* 全局变量 */
char OutputBuffer[100];
char InputBuffer[100];
/* 函数声明 */
BOOL InstallDriver( SC_HANDLE, LPCTSTR, LPCTSTR );
BOOL RemoveDriver( SC_HANDLE, LPCTSTR );
BOOL StartDriver( SC_HANDLE , LPCTSTR );
BOOL StopDriver( SC_HANDLE , LPCTSTR );

/*************************************
* InstallDriver
* 功能 创建服务、安装驱动
* 参数 SchSCManager,服务控制器句柄
*         DriverName,服务名
*         ServiceExe,驱动的可执行程序路径
**************************************/
BOOL InstallDriver(
				   SC_HANDLE SchSCManager,
				   LPCTSTR DriverName,
				   LPCTSTR ServiceExe
				   )
{
	SC_HANDLE schService;
	DWORD err;

	// 调用CreateService创建服务
	schService = CreateService(SchSCManager, // 服务控制器,SCM句柄
		DriverName, // 服务名
		DriverName, // 服务的显示名
		SERVICE_ALL_ACCESS, // 存取权限
		SERVICE_KERNEL_DRIVER, // 服务类型
		SERVICE_DEMAND_START, // 启动类型
		SERVICE_ERROR_NORMAL, // 启动错误的处理
		ServiceExe, // 可执行程序
		NULL, NULL, NULL, NULL, NULL
		);

	if (schService == NULL)
	{
		// 创建服务失败
		err = GetLastError();
		// 服务已经存在
		if (err == ERROR_SERVICE_EXISTS)
		{
			return TRUE;// 返回成功
		}
		else
		{
			// 输出错误信息,返回失败
			printf("CreateService failed! Error = %d \n", err );
			return FALSE;
		}
	}
	// 创建成功,关闭服务
	if (schService)
	{
		CloseServiceHandle(schService);
	}
	// 返回成功
	return TRUE;
}

/*************************************
* RemoveDriver
* 功能 删除驱动服务
* 参数 SchSCManager,服务控制器句柄
*         DriverName,服务名
**************************************/
BOOL RemoveDriver(
			 SC_HANDLE SchSCManager,
			 LPCTSTR DriverName
			 )
{
	SC_HANDLE schService;
	BOOLEAN rCode;

	// 打开服务
	schService = OpenService(SchSCManager,
		DriverName,
		SERVICE_ALL_ACCESS
		);

	if (schService == NULL)
	{
		// 服务打开失败
		printf("OpenService failed! Error = %d \n", GetLastError());
		return FALSE;
	}

	// 删除服务
	if (DeleteService(schService))
	{
		rCode = TRUE;
	} 
	else
	{
		//失败
		printf("DeleteService failed! Error = %d \n", GetLastError());
		rCode = FALSE;
	}

	// 关闭服务句柄
	if (schService)
	{
		CloseServiceHandle(schService);
	}
	return rCode;
}

/*************************************
* StartDriver
* 功能 起动服务,加载执行驱动
* 参数 SchSCManager,服务控制器句柄
*         DriverName,服务名
**************************************/
BOOL StartDriver(
			SC_HANDLE SchSCManager,
			LPCTSTR DriverName
			)
{
	SC_HANDLE schService;
	DWORD err;

	// 打开服务
	schService = OpenService(SchSCManager,
		DriverName,
		SERVICE_ALL_ACCESS
		);
	if (schService == NULL)
	{
		// 失败
		printf("OpenService failed! Error = %d \n", GetLastError());
		return FALSE;
	}

	// 启动服务
	if (!StartService(schService, // 服务句柄
		0, // 参数个数,无
		NULL // 参数指针,无
		))
	{
		// 启动失败
		err = GetLastError();
		// 已经开始运行
		if (err == ERROR_SERVICE_ALREADY_RUNNING)
		{
			// 返回成功
			return TRUE;
		}
		else
		{
			// 失败,打印错误
			printf("StartService failure! Error = %d \n", err );
			return FALSE;
		}
	}

	// 关闭服务句柄
	if (schService)
	{
		CloseServiceHandle(schService);
	}

	return TRUE;

}

/*************************************
* StopDriver
* 功能 停止服务,停止驱动运行
* 参数 SchSCManager,服务控制器句柄
*         DriverName,服务名
**************************************/
BOOL StopDriver(
		   SC_HANDLE SchSCManager,
		   LPCTSTR DriverName
		   )
{
	BOOLEAN rCode = TRUE;
	SC_HANDLE schService;
	SERVICE_STATUS serviceStatus;

	// 打开服务
	schService = OpenService(SchSCManager,
		DriverName,
		SERVICE_ALL_ACCESS
		);

	if (schService == NULL)
	{
		// 失败
		printf("OpenService failed! Error = %d \n", GetLastError());
		return FALSE;
	}

	// 停止运行
	if (ControlService(schService,
		SERVICE_CONTROL_STOP,
		&serviceStatus
		))
	{
		rCode = TRUE;
	}
	else 
	{
		// 失败
		printf("ControlService failed! Error = %d \n", GetLastError() );
		rCode = FALSE;
	}

	// 关闭服务句柄
	if (schService)
	{
		CloseServiceHandle (schService);
	}
	return rCode;

} 

/*************************************
* GetDriverPath
* 功能 获得服务驱动的路径
* 参数 DriverLocation,返回驱动的路径
**************************************/
BOOL GetDriverPath(
				LPSTR DriverLocation
				)
{

	DWORD driverLocLen = 0;

	// 驱动.sys文件在本程序同一目标下
	driverLocLen = GetCurrentDirectory(MAX_PATH,
		DriverLocation
		);

	if (!driverLocLen)
	{
		printf("GetCurrentDirectory failed! Error = %d \n", GetLastError());
		return FALSE;
	}

	// 构造路径,加上驱动名
	lstrcat(DriverLocation, "\\");
	lstrcat(DriverLocation, DRIVER_NAME);
	lstrcat(DriverLocation, ".sys");

	return TRUE;
}

/*************************************
* int _cdecl main( )
* 功能 加载驱动,进行控制
**************************************/
int _cdecl main()
{
	HANDLE hDevice;
	BOOL bRc;
	ULONG bytesReturned;
	DWORD errNum = 0;
	UCHAR driverLocation[MAX_PATH];

	SC_HANDLE schSCManager;// 服务控制器句柄
	// 打开服务控制器,后续安装、启动都会使用到。
	schSCManager = OpenSCManager(NULL, // 本机
		NULL, // 本机数据库
		SC_MANAGER_ALL_ACCESS // 存取权限
		);
	if (!schSCManager)
	{
		// 打开失败
		printf("Open SC Manager failed! Error = %d \n", GetLastError());
		return 1;
	}
	// 获得驱动文件的路径
	if (!GetDriverPath(driverLocation))
	{
		return 1;
	}
	// 安装驱动服务
	if (InstallDriver(schSCManager,
		DRIVER_NAME,
		driverLocation
		))
	{
		// 安装成功,启动服务,运行驱动
		if(!StartDriver(schSCManager, DRIVER_NAME ))
		{
			printf("Unable to start driver. \n");
			return 1;
		}
	}
	else
	{
		// 安装失败,删除驱动。
		RemoveDriver(schSCManager, DRIVER_NAME );
		printf("Unable to install driver. \n");
		return 1;
	}
	// 打开驱动,获得控制所用的句柄
	// 由驱动创建的符号链接
	hDevice = CreateFile( "\\\\.\\IoctlTest",
		GENERIC_READ | GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if ( hDevice == INVALID_HANDLE_VALUE )
	{
		printf ( "Error: CreatFile Failed : %d\n", GetLastError());
		return 1;
	}

	// 打印,输入输出。
	printf("InputBuffer Pointer = %p, BufLength = %d\n", InputBuffer,
		sizeof(InputBuffer));
	printf("OutputBuffer Pointer = %p BufLength = %d\n", OutputBuffer,
		sizeof(OutputBuffer));
	
	// 输入到内核的数据,
	lstrcpy(InputBuffer,
		"This String is from User Application; using IOCTL_XIOCTL_BUFFER");
	printf("\nCalling DeviceIoControl IOCTL_XIOCTL_BUFFER:\n");
	
	// 清空输出缓存
	memset(OutputBuffer, 0, sizeof(OutputBuffer));
	// 进行IO控制,
	bRc = DeviceIoControl ( hDevice,// 句柄
		(DWORD) IOCTL_XIOCTL_BUFFER,// IOCTL
		&InputBuffer,// 输入数据
		strlen ( InputBuffer )+1,// 输入数据的长度
		&OutputBuffer,// 输出数据
		sizeof( OutputBuffer),// 输出数据长度
		&bytesReturned,// 实际输出的数据长度
		NULL
		);
	// 判断是否成功
	if ( !bRc )
	{
		printf ( "Error in DeviceIoControl : %d", GetLastError());
		return 1;
	}
	// 打印从内核输出的内容
	printf(" OutBuffer (%d): %s\n", bytesReturned, OutputBuffer);
	// 关闭句柄
	CloseHandle ( hDevice );
	// 停止运行
	StopDriver(schSCManager,
		DRIVER_NAME
		);
	// 删除服务
	RemoveDriver(schSCManager,
		DRIVER_NAME
		);
	// 关闭服务控制器
	CloseServiceHandle (schSCManager);
	return 0;
}

实现ring3下面的调用

/* 头文件 */
#include <Windows.h>
#include <Winioctl.h>
#include <stdio.h>
/* 函数声明 */
DWORD EnjectCdrom(LPSTR szCdRomName);
DWORD PrintNTFSInfo(LPSTR szVolumeName);

/*************************************
* main
* 功能	-cdrom <盘符> 弹出光盘
*			-ntfs <盘符> 显示nfts分区的信息
**************************************/
int main(int argc, char* argv[])
{
	CHAR szName[64];
	if(argc == 3)
	{
		// 构造设备名
		wsprintf(szName, "\\\\.\\%s.", argv[2]);
		// 弹出光盘
		if(lstrcmp(argv[1],"-cdrom") == 0)
		{
			EnjectCdrom( szName );
			return 0;
		}
		// 获取NTFS分区详细信息
		if(lstrcmp(argv[1],"-ntfs") == 0)
		{
			PrintNTFSInfo( szName );
			return 0;
		}
	}
	// 使用方法
	printf("usage:  \n\t %s -cdrom <volume>\n\t %s -ntfs <volume>\nlike this: \n\t -cdrom G:", 
		argv[0], argv[0]);

	return 0;
}

/*************************************
* DWORD EnjectCdrom(LPSTR szCdRomName)
* 功能	弹出指定的光盘
* 参数	szCdRomName,设备名
**************************************/
DWORD EnjectCdrom(LPSTR szCdRomName)
{
	HANDLE hDevice;
	DWORD dwBytesReturned;

	hDevice = CreateFile(szCdRomName, // 设备名
		GENERIC_ALL, // 存取权限
		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, // 共享方式
		NULL, // 默认安全属性
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL, 
		NULL); 
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("Could not open file (error %d)\n", GetLastError());
		return 0;
	}
	// 发送IOCTL
	if(!DeviceIoControl(
		(HANDLE) hDevice, // 设备句柄
		IOCTL_STORAGE_EJECT_MEDIA, // 控制码
		NULL, // 输入缓存
		0, // 输入缓存大小
		NULL, // 输出缓存
		0, // 输出缓存大小
		&dwBytesReturned, // 实际需要的输输入缓存大小
		NULL // 非OVERLAPPED
		))
	{
		printf("DeviceIoControl error (%d)",GetLastError());
		return 0;
	}
	return 1;

}

/*************************************
* DWORD PrintNTFSInfo(LPSTR szVolumeName)
* 功能	获取显示指定的NTFS驱动器信息
* 参数	szVolumeName,设备名
**************************************/
DWORD PrintNTFSInfo(LPSTR szVolumeName)
{
	// FSCTL_GET_NTFS_VOLUME_DATA IO控制的返回值保存在
	// NTFS_VOLUME_DATA_BUFFER结构中
	NTFS_VOLUME_DATA_BUFFER nvdb;
	DWORD dwBufferSize;
	HANDLE hDevice;
	// 清空参数
	ZeroMemory(&nvdb,sizeof(nvdb));

	hDevice = CreateFile(szVolumeName, 
		GENERIC_ALL, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		NULL, 
		OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL); 
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("Could not open file (error %d)\n", GetLastError());
		return 0;
	}

	if(DeviceIoControl(
		hDevice, // 设备句柄
		FSCTL_GET_NTFS_VOLUME_DATA, // 控制码
		NULL, // 输入缓存
		0, // 输入缓存大小
		&nvdb, // 输出缓存
		sizeof( NTFS_VOLUME_DATA_BUFFER ), // 输出缓存大小
		&dwBufferSize, // 返回的实际数据大小
		NULL // 非OVERLAPPED
		))
	{
		// 打印获取的信息
		printf("SerialNumber %lu\n",nvdb.VolumeSerialNumber);
		printf("Starting logical cluster number of the master file table: %lu\n",nvdb.MftStartLcn);
		printf("Length of the master file table: %lu\n",nvdb.MftValidDataLength);
		printf("... ...\n");
	}
	else
	{
		printf("DeviceIoControl error: (%d)\n",GetLastError());
		return 0;
	}
	return 1;
}


 


/* 头文件 */
#include <Windows.h>
#include <Winioctl.h>
#include <stdio.h>
/* 函数声明 */
DWORD EnjectCdrom(LPSTR szCdRomName);
DWORD PrintNTFSInfo(LPSTR szVolumeName);

/*************************************
* main
* 功能	-cdrom <盘符> 弹出光盘
*			-ntfs <盘符> 显示nfts分区的信息
**************************************/
int main(int argc, char* argv[])
{
	CHAR szName[64];
	if(argc == 3)
	{
		// 构造设备名
		wsprintf(szName, "\\\\.\\%s.", argv[2]);
		// 弹出光盘
		if(lstrcmp(argv[1],"-cdrom") == 0)
		{
			EnjectCdrom( szName );
			return 0;
		}
		// 获取NTFS分区详细信息
		if(lstrcmp(argv[1],"-ntfs") == 0)
		{
			PrintNTFSInfo( szName );
			return 0;
		}
	}
	// 使用方法
	printf("usage:  \n\t %s -cdrom <volume>\n\t %s -ntfs <volume>\nlike this: \n\t -cdrom G:", 
		argv[0], argv[0]);

	return 0;
}

/*************************************
* DWORD EnjectCdrom(LPSTR szCdRomName)
* 功能	弹出指定的光盘
* 参数	szCdRomName,设备名
**************************************/
DWORD EnjectCdrom(LPSTR szCdRomName)
{
	HANDLE hDevice;
	DWORD dwBytesReturned;

	hDevice = CreateFile(szCdRomName, // 设备名
		GENERIC_ALL, // 存取权限
		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, // 共享方式
		NULL, // 默认安全属性
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL, 
		NULL); 
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("Could not open file (error %d)\n", GetLastError());
		return 0;
	}
	// 发送IOCTL
	if(!DeviceIoControl(
		(HANDLE) hDevice, // 设备句柄
		IOCTL_STORAGE_EJECT_MEDIA, // 控制码
		NULL, // 输入缓存
		0, // 输入缓存大小
		NULL, // 输出缓存
		0, // 输出缓存大小
		&dwBytesReturned, // 实际需要的输输入缓存大小
		NULL // 非OVERLAPPED
		))
	{
		printf("DeviceIoControl error (%d)",GetLastError());
		return 0;
	}
	return 1;

}

/*************************************
* DWORD PrintNTFSInfo(LPSTR szVolumeName)
* 功能	获取显示指定的NTFS驱动器信息
* 参数	szVolumeName,设备名
**************************************/
DWORD PrintNTFSInfo(LPSTR szVolumeName)
{
	// FSCTL_GET_NTFS_VOLUME_DATA IO控制的返回值保存在
	// NTFS_VOLUME_DATA_BUFFER结构中
	NTFS_VOLUME_DATA_BUFFER nvdb;
	DWORD dwBufferSize;
	HANDLE hDevice;
	// 清空参数
	ZeroMemory(&nvdb,sizeof(nvdb));

	hDevice = CreateFile(szVolumeName, 
		GENERIC_ALL, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		NULL, 
		OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL); 
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("Could not open file (error %d)\n", GetLastError());
		return 0;
	}

	if(DeviceIoControl(
		hDevice, // 设备句柄
		FSCTL_GET_NTFS_VOLUME_DATA, // 控制码
		NULL, // 输入缓存
		0, // 输入缓存大小
		&nvdb, // 输出缓存
		sizeof( NTFS_VOLUME_DATA_BUFFER ), // 输出缓存大小
		&dwBufferSize, // 返回的实际数据大小
		NULL // 非OVERLAPPED
		))
	{
		// 打印获取的信息
		printf("SerialNumber %lu\n",nvdb.VolumeSerialNumber);
		printf("Starting logical cluster number of the master file table: %lu\n",nvdb.MftStartLcn);
		printf("Length of the master file table: %lu\n",nvdb.MftValidDataLength);
		printf("... ...\n");
	}
	else
	{
		printf("DeviceIoControl error: (%d)\n",GetLastError());
		return 0;
	}
	return 1;
}


 

你可能感兴趣的:(编程,C++,windows,IO,null,代码分析)