我们在进行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;
}