DeviceIoControl:通过API访问设备驱动程序;并获取window文件/文件夹id

时间:2024-03-03 19:37:33

1.设备句柄可以用API函数CreateFile获得。它的原型为

HANDLE CreateFile(

    LPCTSTR lpFileName,                         // 文件名/设备路径

    DWORD dwDesiredAccess,                      // 访问方式

    DWORD dwShareMode,                          // 共享方式

    LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全描述符指针

    DWORD dwCreationDisposition,                // 创建方式

    DWORD dwFlagsAndAttributes,                 // 文件属性及标志

    HANDLE hTemplateFile                        // 模板文件的句柄

);

2.DeviceIoControl的函数原型为

BOOL DeviceIoControl(

    HANDLE hDevice,              // 设备句柄

    DWORD dwIoControlCode,       // 控制码

    LPVOID lpInBuffer,           // 输入数据缓冲区指针

    DWORD nInBufferSize,         // 输入数据缓冲区长度

    LPVOID lpOutBuffer,          // 输出数据缓冲区指针

    DWORD nOutBufferSize,        // 输出数据缓冲区长度

    LPDWORD lpBytesReturned,     // 输出数据实际长度单元长度

    LPOVERLAPPED lpOverlapped    // 重叠操作结构指针

);

3.通过DeviceIoControl获取硬盘的基本参数示例

#include <windows.h>
#include <winioctl.h>
BOOL GetDriveGeometry(DISK_GEOMETRY *pdg)
{
    HANDLE hDevice;               // handle to the drive to be examined
    BOOL bResult;                 // results flag
    DWORD junk;                   // discard results
    hDevice = CreateFile("////.//PhysicalDrive0",  // drive to open
                    0,                // no access to the drive
                    FILE_SHARE_READ | // share mode
                    FILE_SHARE_WRITE,
                    NULL,             // default security attributes
                    OPEN_EXISTING,    // disposition
                    0,                // file attributes
                    NULL);            // do not copy file attributes
    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        return (FALSE);
    }
    bResult = DeviceIoControl(hDevice,     // device to be queried
        IOCTL_DISK_GET_DRIVE_GEOMETRY,     // operation to perform
                    NULL, 0,               // no input buffer
                    pdg, sizeof(*pdg),     // output buffer
                    &junk,                 // # bytes returned
                    (LPOVERLAPPED) NULL);  // synchronous I/O
    CloseHandle(hDevice);
    return (bResult);
}
int main(int argc, char *argv[])
{
    DISK_GEOMETRY pdg;            // disk drive geometry structure
    BOOL bResult;                 // generic results flag
    ULONGLONG DiskSize;           // size of the drive, in bytes
    bResult = GetDriveGeometry (&pdg);
    if (bResult)
    {
        printf("Cylinders = %I64d/n", pdg.Cylinders);
        printf("Tracks per cylinder = %ld/n", (ULONG) pdg.TracksPerCylinder);
        printf("Sectors per track = %ld/n", (ULONG) pdg.SectorsPerTrack);
        printf("Bytes per sector = %ld/n", (ULONG) pdg.BytesPerSector);
  
        DiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *
            (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;
        printf("Disk size = %I64d (Bytes) = %I64d (Mb)/n", DiskSize,
            DiskSize / (1024 * 1024));
    }
    else
    {
        printf("GetDriveGeometry failed. Error %ld./n", GetLastError());
    }
    return ((int)bResult);
}

注:以上是从别的地方参考获取的,至于地址已经忘了,见谅~

4.获取window文件/文件夹id,如打开中的doc文件也可获取到

在window下,每个文件/文件夹都有一个专属的id,即便是拷贝的一个相同的文件,在window下的id都是不一样的。不过,office的文件会有所不同,如果你用office的文件执行了修改并保存,其实它的实际操作是你打开文件时,会创建一个缓存文件,然后当你修改完成并保存后,它会把当前的文件拷贝并到缓存文件中、删除原文件、重命名缓存文件,其实就相当于创建一个新的文件。所以,修改office文件,它window的id是会变化的。

但其它的文件则是唯一的。下面是获取的方法:

HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD cbOut;  
FILE_OBJECTID_BUFFER buf = {0};
QFileInfo file(filePath);
if (file.isDir())
{
    hFile = CreateFile((wchar_t*)filePath.utf16(), 
    FILE_LIST_DIRECTORY, 
    FILE_SHARE_READ | FILE_SHARE_WRITE ,
        NULL, //security attributes
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS | //<- the required priviliges for this flag are: SE_BACKUP_NAME and SE_RESTORE_NAME.  CPrivilegeEnabler takes care of that.
        NULL,
        NULL);
    }
    else
    {
        hFile = CreateFile((wchar_t*)filePath.utf16(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    }

    if(hFile == INVALID_HANDLE_VALUE)
    {
        Q_DEBUG() << QString("CreateFile (%1) failed with: %2").arg(filePath).arg(GetLastError());
        fileID = "";
        return ret;
    }

    if (DeviceIoControl(hFile, FSCTL_CREATE_OR_GET_OBJECT_ID, NULL, 0, &buf, sizeof(buf), &cbOut, NULL)) //DeviceIoControl仅支持NTFS
    {  
        GUID guid;  
        CopyMemory(&guid, &buf.ObjectId, sizeof(GUID));  
        WCHAR szGuid[39];  
        StringFromGUID2(guid, szGuid, 39);
        fileID = QString::fromStdWString(szGuid);
        ret = true;
    }  

    CloseHandle(hFile);