HANDLE hDevice = CreateFile(L"\\\\.\\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
时间: 2023-07-21 15:27:11 浏览: 92
这个示例使用CreateFile打开了一个名为PhysicalDrive0的物理磁盘设备,以便读取其内容。以下是对该函数调用中参数的解释:
- L"\\\\.\\PhysicalDrive0":设备名称,这个名称表示物理磁盘0,通常是系统启动磁盘。
- GENERIC_READ:访问权限,指定可以从设备中读取数据。
- FILE_SHARE_READ | FILE_SHARE_WRITE:共享模式,指定其他进程可以同时读取或写入这个设备。
- NULL:安全描述符,指定设备的安全描述符,通常为NULL。
- OPEN_EXISTING:创建选项,指定打开一个已经存在的设备。
- NULL:文件属性,指定设备的文件属性,通常为NULL。
需要注意的是,访问磁盘设备需要管理员权限,否则可能会出现访问被拒绝的错误。另外,对于磁盘设备的读取和写入操作,需要使用ReadFile和WriteFile等Windows API函数。
相关问题
java获取u盘_java实现监听u盘示例分享
Java可以通过JDK中的Java Native Interface(JNI)调用操作系统的API来获取U盘的插拔事件,从而实现对U盘的监听。下面是一个简单的示例代码,演示了如何在Java中监听U盘的插拔事件:
```java
import java.io.File;
import java.util.Arrays;
public class USBListener {
static {
System.loadLibrary("USBListener");
}
public static native void start();
public static void main(String[] args) {
USBListener.start();
}
public static void onUSBInserted(String drivePath) {
System.out.println("U盘已插入:" + drivePath);
}
public static void onUSBRemoved(String drivePath) {
System.out.println("U盘已拔出:" + drivePath);
}
}
```
上述代码中,我们定义了一个`USBListener`类,其中包含了一个`start()`方法,用于启动U盘监听功能。在`start()`方法中,我们通过JNI调用了一个名为`startUSBListener()`的C++函数,该函数启动了一个线程,循环遍历系统中的所有驱动器,并检查它们是否是可移动设备。如果是可移动设备,则将其保存到一个列表中,并且在后续的循环中持续检查它们是否被插拔。
当U盘被插入或拔出时,`startUSBListener()`函数会调用`onUSBInserted()`或`onUSBRemoved()`方法,这两个方法都是Java中的静态方法,可以在任何地方被调用。在本例中,我们只是简单地打印了一条消息,表示U盘已经插入或拔出了。
我们还需要在C++中实现`startUSBListener()`函数的代码,这里我们使用了Windows API来获取系统中的驱动器列表,并检查它们是否是可移动设备。以下是`startUSBListener()`函数的C++实现代码:
```cpp
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "USBListener.h"
#define MAX_DRIVES 26
void startUSBListener(JNIEnv *env, jclass cls) {
DWORD drives = GetLogicalDrives();
char driveLetter[] = "A:\\";
for (int i = 0; i < MAX_DRIVES; i++) {
if ((drives & (1 << i)) != 0) {
driveLetter[0] = 'A' + i;
UINT type = GetDriveType(driveLetter);
if (type == DRIVE_REMOVABLE) {
HANDLE hDevice = CreateFile(driveLetter, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE) {
char buf[MAX_PATH];
DWORD len;
if (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &buf, sizeof(buf), &len, NULL)) {
STORAGE_DEVICE_NUMBER *number = (STORAGE_DEVICE_NUMBER *) &buf;
char drivePath[MAX_PATH];
sprintf(drivePath, "\\\\.\\PhysicalDrive%d", number->DeviceNumber);
HANDLE hDrive = CreateFile(drivePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDrive != INVALID_HANDLE_VALUE) {
OVERLAPPED overlapped = {};
char buffer[512];
DWORD bytesReturned;
if (DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &buf, sizeof(buf), &len, &overlapped)) {
while (1) {
Sleep(1000);
if (DeviceIoControl(hDrive, IOCTL_STORAGE_CHECK_VERIFY2, NULL, 0, NULL, 0, &bytesReturned, &overlapped)) {
USBListener::onUSBRemoved(driveLetter);
break;
} else {
if (GetLastError() == ERROR_NOT_READY) {
USBListener::onUSBInserted(driveLetter);
break;
}
}
}
}
CloseHandle(hDrive);
}
}
CloseHandle(hDevice);
}
}
}
}
}
```
在上述代码中,我们首先调用`GetLogicalDrives()`函数获取系统中所有的驱动器列表,然后遍历这个列表,并检查每个驱动器是否是可移动设备。如果是可移动设备,则使用`CreateFile()`函数打开该设备,并获取其设备号。然后,我们将设备号作为参数,使用`CreateFile()`函数打开该设备对应的物理驱动器,并调用`DeviceIoControl()`函数发送`IOCTL_STORAGE_CHECK_VERIFY2`控制码,以检查该U盘是否已经被插入或拔出。
如果`DeviceIoControl()`函数返回了`ERROR_NOT_READY`错误码,则表示该U盘已经被拔出,我们就调用`USBListener::onUSBRemoved()`方法通知Java代码;如果`DeviceIoControl()`函数成功返回,则表示该U盘已经被插入,我们就调用`USBListener::onUSBInserted()`方法通知Java代码。在检测到U盘被插入或拔出后,我们需要使用`Sleep()`函数等待一段时间,以避免频繁地检查设备状态导致CPU占用过高。
最后,我们需要使用JNI将C++代码编译成动态链接库,以供Java代码调用。以下是`USBListener.h`文件的内容:
```cpp
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_USBListener_startUSBListener(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
```
然后,我们需要使用C++编译器将上述代码编译成动态链接库,以供Java代码调用。在Windows下,可以使用MinGW或Visual C++等编译器来编译,例如:
```bash
g++ -shared -o USBListener.dll -I"C:\Program Files\Java\jdk1.8.0_231\include" -I"C:\Program Files\Java\jdk1.8.0_231\include\win32" USBListener.cpp
```
编译完成后,我们就可以在Java代码中使用`System.loadLibrary()`方法加载该动态链接库,并调用`USBListener.start()`方法启动U盘监听功能了。
windows下用C++实现SCSI READ一次命令读取512K数据代码
以下是一个简单的 C++ 代码示例,用于在 Windows 环境下使用 SCSI READ 命令读取 512K 数据:
```c++
#include <windows.h>
#include <winioctl.h>
#define SECTOR_SIZE 512
#define BUFFER_SIZE (SECTOR_SIZE * 1024)
int main()
{
HANDLE hDevice = CreateFile("\\\\.\\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("Failed to open device, error code: %d\n", GetLastError());
return 1;
}
BYTE buffer[BUFFER_SIZE] = { 0 };
DWORD bytesReturned = 0;
STORAGE_PROPERTY_QUERY storagePropertyQuery = { 0 };
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
storagePropertyQuery.PropertyId = StorageAdapterProperty;
storagePropertyQuery.QueryType = PropertyStandardQuery;
if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery, sizeof(storagePropertyQuery), &storageDescriptorHeader,
sizeof(storageDescriptorHeader), &bytesReturned, NULL))
{
printf("Failed to retrieve adapter property, error code: %d\n", GetLastError());
CloseHandle(hDevice);
return 1;
}
STORAGE_READ_CAPACITY readCapacity = { 0 };
if (!DeviceIoControl(hDevice, IOCTL_STORAGE_READ_CAPACITY, NULL, 0, &readCapacity,
sizeof(readCapacity), &bytesReturned, NULL))
{
printf("Failed to retrieve read capacity, error code: %d\n", GetLastError());
CloseHandle(hDevice);
return 1;
}
DWORD sectorCount = readCapacity.DiskLength.QuadPart / SECTOR_SIZE;
DWORD startingSector = 0;
if (!DeviceIoControl(hDevice, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0,
&bytesReturned, NULL))
{
printf("Failed to verify device, error code: %d\n", GetLastError());
CloseHandle(hDevice);
return 1;
}
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb = { 0 };
sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
sptdwb.sptd.PathId = 0;
sptdwb.sptd.TargetId = 0;
sptdwb.sptd.Lun = 0;
sptdwb.sptd.TimeOutValue = 2;
sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_IN;
sptdwb.sptd.DataTransferLength = BUFFER_SIZE;
sptdwb.sptd.DataBuffer = buffer;
sptdwb.sptd.SenseInfoLength = SPT_SENSE_LENGTH;
sptdwb.sptd.CdbLength = 10;
sptdwb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf);
sptdwb.sptd.Cdb[0] = 0x28; // SCSI READ command
sptdwb.sptd.Cdb[1] = 0;
sptdwb.sptd.Cdb[2] = (startingSector >> 24) & 0xFF;
sptdwb.sptd.Cdb[3] = (startingSector >> 16) & 0xFF;
sptdwb.sptd.Cdb[4] = (startingSector >> 8) & 0xFF;
sptdwb.sptd.Cdb[5] = startingSector & 0xFF;
sptdwb.sptd.Cdb[6] = 0;
sptdwb.sptd.Cdb[7] = (BUFFER_SIZE / SECTOR_SIZE) & 0xFF;
sptdwb.sptd.Cdb[8] = 0;
sptdwb.sptd.Cdb[9] = 0;
if (!DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptdwb,
sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), &sptdwb,
sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), &bytesReturned, NULL))
{
printf("Failed to execute SCSI READ command, error code: %d\n", GetLastError());
CloseHandle(hDevice);
return 1;
}
CloseHandle(hDevice);
return 0;
}
```
请注意,这只是一个简单的示例代码,可能需要根据实际情况进行更改。同时,使用 SCSI 命令需要具有足够的权限,并且必须小心谨慎,以免意外损坏设备。