0

This code is perfectly fine when launched on Windows 7:

HANDLE hVol = CreateFile(L"\\\\.\\c:", GENERIC_WRITE | GENERIC_READ, 
                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
// hVol is always successful (both of Win7 and 10), I double-checked
BYTE pData[sizeof(DWORDLONG) + 0x10000];
DWORD cb;
MFT_ENUM_DATA med;
med.StartFileReferenceNumber = 0;
med.LowUsn = 0;
med.HighUsn = MAXLONGLONG;
DeviceIoControl(hVol, FSCTL_ENUM_USN_DATA, &med, sizeof(med), pData, sizeof(pData), &cb, NULL);
err = GetLastError();

but I get error 87 (ERROR_INVALID_PARAMETER) when running it on Windows 10. What could be the reason?

Basj
  • 41,386
  • 99
  • 383
  • 673

1 Answers1

4

MFT_ENUM_DATA this is really typedef which expanded to MFT_ENUM_DATA_V0 or MFT_ENUM_DATA_V1 depend from NTDDI_VERSION :

#if (NTDDI_VERSION >= NTDDI_WIN8)
typedef MFT_ENUM_DATA_V1 MFT_ENUM_DATA, *PMFT_ENUM_DATA;
#else
typedef MFT_ENUM_DATA_V0 MFT_ENUM_DATA, *PMFT_ENUM_DATA;
#endif

obviously the in your case NTDDI_VERSION >= NTDDI_WIN8 and you use MFT_ENUM_DATA_V1.

and you not initialize MaxMajorVersion which must be set to 2 or 3.

so you need or add line med.MaxMajorVersion = 2; (or 3). or use MFT_ENUM_DATA_V0 med={};

RbMm
  • 31,280
  • 3
  • 35
  • 56
  • `#if (NTDDI_VERSION >= NTDDI_WIN8)` is evaluated at compile time. The OP is running the *same* binary on both systems, so that is unrelated to the issue. – IInspectable Jul 31 '17 at 23:45
  • @IInspectable - of course evaluated in compile time. and so what ? – RbMm Jul 31 '17 at 23:46
  • I compiled on Win7, and tested the same .exe on both Win7 and Win10. I agree with you @IInspectable : it is evaluated at compile time. But strangely, doing `MFT_ENUM_DATA_V0 med;` solved the problem :) (thanks a lot RbMm!) – Basj Jul 31 '17 at 23:46
  • 1
    @Basj - **where** you compile - absolute not important. important what version of sdk you use (I assume you not define `NTDDI_VERSION` yourself direct) – RbMm Jul 31 '17 at 23:48
  • @RbMm that's right. I checked: at compile time (on Win7, but this doesn't matter), because of the SDK I have, I see `NTDDI_VERSION >= NTDDI_WIN8` is true, so this is applied: `typedef MFT_ENUM_DATA_V1 MFT_ENUM_DATA, *PMFT_ENUM_DATA;` – Basj Jul 31 '17 at 23:53
  • Last thing @RbMm, do you thing using `_V0` or `_V1` (or `med.MaxMajorVersion = 2` or `3`) will change a little bit the performance [of the enumeration](https://msdn.microsoft.com/en-us/library/windows/desktop/aa364563(v=vs.85).aspx)? – Basj Jul 31 '17 at 23:54
  • @Basj - the smaller structure - more count of structures in the same buffer. must be faster (but hard say how more). from another side higher structure version have additional info. but it can be not supported by os. really now `MaxMajorVersion` can be 2 or 3 or 4 (on win 10) and output up to `USN_RECORD_V4`. but win7 support only `USN_RECORD_V2` – RbMm Aug 01 '17 at 00:03
  • Thanks again @RbMm. I wish I could +100 for this answer (I was stuck since a few hours...) – Basj Aug 01 '17 at 00:04
  • @Basj - if you want better performance - use large buffer (say 16mb) - with this you got less counts of DeviceIoControl. – RbMm Aug 01 '17 at 00:35