after creating a VSS snapshot I'd like to be able to query the USN journal. Is this possible or is the USN journal not accessible from a VSS snapshot?
my goal is to be able to use the USN journal in an incremental backup between two VSS snapshots. The process for the backup would be to
- take a VSS Snapshot and backup the volume, taking note of the USN entries for each file
- ...use the filesystem, add/delete/modify files
- take a second VSS snapshot, then use the USN journal to detect anything that changed during step #2
what I'm failing with right now is the part where I'm trying to get a hold of the highest USN entry on the VSS snapshot
- create VSS Snapshot
- open the snapshot with CreateFile(\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy25)
- DeviceIoControl(FSCTL_QUERY_USN_JOURNAL) - this fails with GLE:1179 "the volume change journal is not active"
I can simulate this from the commandline as follows
C:\>vssadmin list shadows
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.
Contents of shadow copy set ID: {54fc99fb-65f2-4558-8e12-9308979327f0}
Contained 1 shadow copies at creation time: 5/10/2012 6:44:19 PM
Shadow Copy ID: {a2d2c155-9916-47d3-96fd-94fae1c2f802}
Original Volume: (T:)\\?\Volume{a420b1fa-9744-11e1-9082-889ffaf52b70}\
Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy25
Originating Machine: computer
Service Machine: computer
Provider: 'Microsoft Software Shadow Copy provider 1.0'
Type: Backup
Attributes: Differential
C:\>fsutil usn queryjournal \\?\Volume{a420b1fa-9744-11e1-9082-889ffaf52b70}
Usn Journal ID : 0x01cd2ebe9c795b57
First Usn : 0x0000000000000000
Next Usn : 0x000000000001b5f8
Lowest Valid Usn : 0x0000000000000000
Max Usn : 0x7fffffffffff0000
Maximum Size : 0x0000000000100000
Allocation Delta : 0x0000000000040000
C:\>fsutil usn queryjournal \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy25
Error: The volume change journal is not active.
Any ideas what I'm doing incorrectly, if this is possible?
This question was very important for the project I'm working on, so I finally got it (almost) 100% working.
Note : all of the below code snippets are in C#
Thanks to the previous answers from Hannes de Jager who pointed me to the right direction and documentations, I can now read an USN journal from a VSS snapshot or any other special device that the regular API cannot work with ; in my case, I mean VMware snapshots mounted using the VDDK (VMware SDK for VM disks).
I also reused or imported code coming from great projects :
USN journal explorer in C#, from StCroixSkipper (http://www.dreamincode.net/forums/blog/1017-stcroixskippers-blog/). Only reads USN using the official API (so no VSS here) but provides useful pinvokes and Win32 API structures as well as general information about how USN works
AlphaFS (https://github.com/alphaleonis/AlphaFS/) , which mimics large parts of the
System.IO
namespace, but allows to access special windows paths (VSS snapshots, raw devices) and provides useful extensions as well.In case anyone else is interested, I share the code I use righ now, still in a rather crude state, but working.
How does it work?
First, you must acess the required Usn journal componenents. They are at the root of the device as ADS (alternate data streams) in an hidden entry. They cannot be accessed using the standard
System.IO
namespace, that's why I previously told I used the AlphaFS project, but pinvokingCreateFile()
andReadFile()
should be enough.1/2
The entry
\$Extend\$UsnJrnl:$Max
has global information about the current state of the journal. The most important parts are the usn journal ID (that you can use to check that the journal has not been reset if you want to compare multiple VSS snapshots) and the lowest valid USN journal sequence number.USN journal structure:
2/2
The entry
\$Extend\$UsnJrnl:$J
contains the journal records. It is a sparse file so its disk usage is much lower than it size.To answer the initial question, how can one know the Max used USN sequence from a previous VSS snapshot and compare it with that of another snapshot? Well, the NextUsn value is simply equals to the size of the
$Usnjrnl:$J
entry.On your "new" vss snapshot USN journal, you can seek to the "reference" VSS snapshot max USN before starting parsing records, if you want to parse the records changed between the two snapshots.
Generally speaking, each USN journal entry as a unique ID (USN number) which is the offset inside
$J
at whch the journal entry itself is located. Each entry has a variable size, so to sequentially read then we have to calculate:Fortunately the record length is a also a field of the USN entry record. Enough said, here is the USN record class:
I tried to isolate the smallest part of code that can parse an USN journal and extract its entries, starting from the lowest valid one. Remember, a record has a variable length; also note that some records point to a next record that is empty (the first 4 bytes, which are normally the record length, are zeroed). In this case I seek 4 bytes and retry parsing, until I get the next record. This behavior also have been reported by people having written similar parsing tools in Python so I guess I'n not too wrong here.
Here are the pinvokes I use:
This is definitely not the best piece of code on earth, but I think it will provide a good starting point for anyone having to do the same thing.