FSCTL_LOOKUP_STREAM_FROM_CLUSTER返回ERROR_INVALID_PARAMETER

时间:2015-05-07 11:47:58

标签: c++ winapi

我的目标是从群集中获取文件名。为此,我使用函数FSCTL_LOOKUP_STREAM_FROM_CLUSTER。使用它时,根据MSDN,我收到的错误87代表 ERROR_INVALID_PARAMETER 。驱动器手柄是正确的,因为我在其他正常工作的功能中使用它。

#include <Windows.h>
#include <iostream>
using namespace std;

class Disk{
public:
    Disk();
    HANDLE hDisk;
    WCHAR *individualName;
    WCHAR *Letter;
};

bool searchFileByItCluster(Disk drive){
    LOOKUP_STREAM_FROM_CLUSTER_INPUT inpStruct;
    LOOKUP_STREAM_FROM_CLUSTER_ENTRY str;
    LOOKUP_STREAM_FROM_CLUSTER_OUTPUT str1;
    PNTFS_VOLUME_DATA_BUFFER info;
    PLARGE_INTEGER INT = (PLARGE_INTEGER)malloc(sizeof(LARGE_INTEGER));
    DWORD cbWritten;
    int size = (sizeof(DWORD) * 2 + sizeof(LARGE_INTEGER));
    inpStruct.NumberOfClusters = 1;
    inpStruct.Cluster[0].QuadPart = 26585528;

    bool ret = DeviceIoControl(drive.hDisk, FSCTL_LOOKUP_STREAM_FROM_CLUSTER, &inpStruct, (sizeof(DWORD) * 2 + sizeof(LARGE_INTEGER)), &str1, sizeof(LOOKUP_STREAM_FROM_CLUSTER_OUTPUT), &cbWritten, NULL);
    if (!ret){
        cout << GetLastError()<<endl<<sizeof(LOOKUP_STREAM_FROM_CLUSTER_INPUT);
        for (int i = 0; i < inpStruct.NumberOfClusters; i++){
            printf("%lli\n", inpStruct.Cluster[i]);
        }


        int i = 0;
    }
    return false;
}

1 个答案:

答案 0 :(得分:0)

相当古老的问题,并没有特别有帮助。但它是google为FSCTL_LOOKUP_STREAM_FROM_CLUSTER找到的为数不多的网页之一。所以现在我已经弄明白了如何使用它,我传递了我所学到的东西。

警告:docs指出:

  

FSCTL_LOOKUP_STREAM_FROM_CLUSTER是一项资源密集型操作,通常使用非常大量的磁盘带宽,内存和时间。

但是,如果你需要它,你需要它(我确实做到了)。出于这个原因,这里有一些对我有用的代码,以及我在途中学到的东西。

// Pick a plausible estimate.  Note: valid output sizes can be up to ~64k!
DWORD bufsize = 
    MAX_PATH + 
    sizeof(LOOKUP_STREAM_FROM_CLUSTER_OUTPUT) + 
    sizeof(LOOKUP_STREAM_FROM_CLUSTER_ENTRY);

LOOKUP_STREAM_FROM_CLUSTER_INPUT sfci;
LOOKUP_STREAM_FROM_CLUSTER_OUTPUT *sfco = 
    (LOOKUP_STREAM_FROM_CLUSTER_OUTPUT *)malloc(bufsize);

sfci.NumberOfClusters = 1;      // Only looking up one cluster
sfci.Flags = 0;                 // No flags are currently defined
sfci.Cluster[0].QuadPart = 123; // Cluster number being sought

// While some DeviceIoControl calls get away with 0 or FILE_READ_ATTRIBUTES,
// FSCTL_LOOKUP_STREAM_FROM_CLUSTER needs at least FILE_READ_DATA.  Also,
// while the docs claim you can use "a file on a NTFS volume," I believe a 
// volume handle is required, which requires running with admin rights.
HANDLE h1 = CreateFile(
    L"\\\\.\\j:", 
    FILE_READ_DATA, 
    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 
    NULL, 
    OPEN_EXISTING, 
    FILE_FLAG_BACKUP_SEMANTICS, // Required, but the SE_BACKUP_NAME priv is not
    NULL);

if (h1 == INVALID_HANDLE_VALUE)
    ;  // Do something

DWORD ret;
BOOL B = DeviceIoControl(
    h1, 
    FSCTL_LOOKUP_STREAM_FROM_CLUSTER, 
    &sfci, 
    sizeof(sfci), 
    sfco, 
    bufsize, 
    &ret, 
    NULL);

if (!B && GetLastError() == ERROR_MORE_DATA)
    ; // bufsize too small. Resize to sfco->BufferSizeRequired and retry

if (!B)
    ; // Some other error

// Here's the data.
LOOKUP_STREAM_FROM_CLUSTER_ENTRY *sfce = 
    (LOOKUP_STREAM_FROM_CLUSTER_ENTRY *)((BYTE *)sfco + sfco->Offset);

有。现在,下次有人谷歌搜索FSCTL_LOOKUP_STREAM_FROM_CLUSTER时,至少他们会打开工作样本。