I am trying to understand and work with win32file. I need to grab USN Journals and having a hard time understanding code snippets I found online. This is the code snippet I found -
format = 'qqqqqLLLLqqqqq'
length = struct.calcsize(format)
out_buffer = win32file.DeviceIoControl(volh, winioctlcon.FSCTL_GET_NTFS_VOLUME_DATA, None, length)
data = struct.unpack(format, out_buffer)
Now I am really rusty when it comes to C and it's structures. What I have understood for now is format
is 96 bytes buffer and it'll get the output from DeviceIoControl
So I tried to change the format to 'QQQQQQQQQQQQQQQQQQQ'
to see what happens(to see because I am kind of clueless what might actually happen) and it turns out I got a larger out_buffer
this time. So I thought to unpack it -
struct.unpack(format, out_buffer)
And surprise to me, I got -
struct.error: unpack requires a string argument of length 152
So I added another 'Q' to increase the size and got the same result. I don't understand why 'qqqqqLLLLqqqqq' works and 'QQQQQQQQQQQQQQQQQQQ' does not. So my questions are -
My understanding was we can unpack if buffer was larger than the output so why doesn't the unpack work?
Would I have to remember these formats every-time I want to get something out from DeviceIoControl?
Pointing me out to resources would also be an added bonus as I need to build on the code to read USN Journals and I don't think hit-and-try is going to get me anywhere
Let's split the problem in smaller pieces and take each one at a time.
win32file module is part of [GitHub]: mhammond/pywin32 - Python for Windows (pywin32) Extensions which is a Python wrapper over WinAPIs
Unfortunately, it doesn't have an official doc page (or I'm not aware of one), so below is the best that I could find (I've been using this for years). An alternative method that never fails (but it's less appealing) is looking directly at the code
[ActiveState.Docs]: win32file.DeviceIoControl is a wrapper over [MS.Docs]: DeviceIoControl function
DeviceIoControl acts differently, depending on the dwIoControlCode (2nd argument). For FSCTL_GET_NTFS_VOLUME_DATA, it fills a buffer with volume specific data. From [MS.Docs]: FSCTL_GET_NTFS_VOLUME_DATA IOCTL:
Here's an alternative to the above broken URL: [MSDN]: NTFS_VOLUME_DATA_BUFFER structure. As I'm not sure for how long will it be valid, I'm pasting the structure definition below (from Windows Kits 8.1: winioctl.h (line #4987)):
[Python 3.Docs]: struct - Interpret bytes as packed binary data module, is used for conversions between binary and "normal" data. It contains all the format characters meanings (q, Q, L, ...), and much more. You could also take a look at [SO]: Python struct.pack() behavior for more (practical) details
After going over the above materials, things should become clearer.
A couple of notes:
I've also prepared a dummy Python example.
code00.py:
Output:
Needless to say that multiplying TotalClusters by BytesPerCluster, I get the correct bytes number (as reported by Win) for my E: drive.