private void FileInfo_Query_FileIdInformation(FileType fileType)
        {
            BaseTestSite.Assume.AreNotEqual(FileSystem.FAT32, fsaAdapter.FileSystem, "File system should not be FAT32.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Test case steps:");
            MessageStatus status;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "1. Create a file.");
            status = this.fsaAdapter.CreateFile(fileType);
            BaseTestSite.Assert.AreEqual(MessageStatus.SUCCESS, status, "Create should succeed.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "2. Query FileIdInformation.");
            byte[] outputBuffer;
            long   byteCount;

            status = this.fsaAdapter.QueryFileInformation(FileInfoClass.FileIdInformation, this.fsaAdapter.transBufferSize, out byteCount, out outputBuffer);
            BaseTestSite.Assert.AreEqual(MessageStatus.SUCCESS, status, "Query FileIdInformation should succeed.");

            FileIdInformation fileIdInfo = TypeMarshal.ToStruct <FileIdInformation>(outputBuffer);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "3. Get FileId by sending FSCTL_READ_FILE_USN_DATA to server.");
            status = this.fsaAdapter.FsCtlReadFileUSNData(3, 3, out outputBuffer); // Only version 3 USN record contains 128 bit FileReferenceNumber;
            BaseTestSite.Assert.AreEqual(MessageStatus.SUCCESS, status, "FSCTL_READ_FILE_USN_DATA should succeed.");
            USN_RECORD_V3 record = TypeMarshal.ToStruct <USN_RECORD_V3>(outputBuffer);

            System.Guid fileId = record.FileReferenceNumber;
            BaseTestSite.Assert.AreEqual(fileId, fileIdInfo.FileId, "FileId when querying FileIdInformation should be the same with FileReferenceNumber when sending FSCTL_READ_FILE_USN_DATA.");

            // We can get the 64-bit VolumeSerialNumber only by sending FSCTL_GET_NTFS_VOLUME_DATA or FSCTL_GET_REFS_VOLUME_DATA.
            // For other file system, just ignore this check.
            if (this.fsaAdapter.FileSystem == FileSystem.NTFS)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "4. Get VolumeSerialNumber by sending FSCTL_GET_NTFS_VOLUME_DATA to server.");
                status = this.fsaAdapter.FsCtlForEasyRequest(FsControlCommand.FSCTL_GET_NTFS_VOLUME_DATA, out outputBuffer);
                BaseTestSite.Assert.AreEqual(MessageStatus.SUCCESS, status, "FSCTL_GET_NTFS_VOLUME_DATA should succeed.");
                NTFS_VOLUME_DATA_BUFFER ntfsVolumeData = TypeMarshal.ToStruct <NTFS_VOLUME_DATA_BUFFER>(outputBuffer);
                long volumeId = ntfsVolumeData.VolumeSerialNumber;
                BaseTestSite.Assert.AreEqual(volumeId, fileIdInfo.VolumeSerialNumber,
                                             "VolumeSerialNumber when querying FileIdInformation should be the same with VolumeSerialNumber when sending FSCTL_GET_NTFS_VOLUME_DATA.");
            }
            else if (this.fsaAdapter.FileSystem == FileSystem.REFS)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "4. Get VolumeSerialNumber by sending FSCTL_GET_REFS_VOLUME_DATA to server.");
                status = this.fsaAdapter.FsCtlForEasyRequest(FsControlCommand.FSCTL_GET_REFS_VOLUME_DATA, out outputBuffer);
                BaseTestSite.Assert.AreEqual(MessageStatus.SUCCESS, status, "FSCTL_GET_REFS_VOLUME_DATA should succeed.");
                REFS_VOLUME_DATA_BUFFER refsVolumeData = TypeMarshal.ToStruct <REFS_VOLUME_DATA_BUFFER>(outputBuffer);
                long volumeId = refsVolumeData.VolumeSerialNumber;
                BaseTestSite.Assert.AreEqual(volumeId, fileIdInfo.VolumeSerialNumber,
                                             "VolumeSerialNumber when querying FileIdInformation should be the same with VolumeSerialNumber when sending FSCTL_GET_REFS_VOLUME_DATA.");
            }
        }
        private static IUSN_RECORD ParseUsnRecord(UnmanagedMemory mem, int dataOffset, out int length)
        {
            // Get record length
            length = Marshal.ReadInt32(mem, dataOffset);
            int majorVersion = Marshal.ReadByte(mem, dataOffset + sizeof(int)) + (Marshal.ReadByte(mem, dataOffset + sizeof(int) + 1) << 8);

            if (length <= 0)
            {
                // No more records
                return(null);
            }

            // Copy out record subset
            switch (majorVersion)
            {
            case 2:
                USN_RECORD_V2 recordv2 = (USN_RECORD_V2)Marshal.PtrToStructure(mem.Handle + dataOffset, typeof(USN_RECORD_V2));

                // Parse string manually, as we cannot rely on the string to be null-terminated.
                recordv2.FileName = Marshal.PtrToStringUni(mem.Handle + dataOffset + recordv2.FileNameOffset, recordv2.FileNameLength / 2);

                return(recordv2);

            case 3:
                USN_RECORD_V3 recordv3 = (USN_RECORD_V3)Marshal.PtrToStructure(mem.Handle + dataOffset, typeof(USN_RECORD_V3));

                // Parse string manually, as we cannot rely on the string to be null-terminated.
                recordv3.FileName = Marshal.PtrToStringUni(mem.Handle + dataOffset + recordv3.FileNameOffset, recordv3.FileNameLength / 2);

                return(recordv3);

            default:
                // Ignore
                Debugger.Break();
                break;
            }

            return(null);
        }