Win32 API 日本語リファレンス
ホームSystem.Ioctl › USN_RECORD_V3

USN_RECORD_V3

構造体
サイズx64: 80 バイト / x86: 80 バイト

サイズ=各フィールドのバイト数(x64/x86 で異なる場合は x64/x86 と併記)。x64/x86 列=フィールドのバイトオフセット(HSPで dupptr / lpoke / wpoke 等に使用)。

フィールド

フィールドサイズx64x86説明
RecordLengthDWORD4+0+0

レコード全体の長さ (バイト単位)。

USN_RECORD_V3 は可変サイズであるため、出力バッファー内の次のレコードのアドレスを計算するときには RecordLength メンバーを使用してください。たとえば、USN_RECORD_V3 を扱う DeviceIoControl 関数の操作から返されるバッファーなどが該当します。

変更ジャーナルのレコードのサイズ (バイト単位) は、最大でも USN_RECORD_V3 構造体のサイズに、MaximumComponentLength 文字から 1 を引いた数 (構造体内で宣言されている文字の分) にワイド文字のサイズを掛けた値を加えたものになります。 MaximumComponentLength の値は GetVolumeInformation 関数を呼び出すことで取得できます。C では、次のコード例のようにしてレコードのサイズを求めることができます。

C++
  MaximumChangeJournalRecordSize = 
      QuadAlign( (MaximumComponentLength - 1) * sizeof(WCHAR) 
       + sizeof(USN_RECORD_V3) );
変更ジャーナル ソフトウェアのバージョンが変わっても互換性を維持するために、実行時の計算によって USN_RECORD_V3 構造体のサイズを求めてください。バージョン変更に対する互換性の詳細については、このトピックの「解説」セクションを参照してください。
MajorVersionWORD2+4+4

このレコードに対応する変更ジャーナル ソフトウェアのメジャー バージョン番号。

たとえば、変更ジャーナル ソフトウェアがバージョン 3.0 の場合、メジャー バージョン番号は 3 です。

意味
2
この構造体は USN_RECORD_V2 構造体であり、 構造体の残りの部分はそのレイアウトを使用して解析する必要があります。
3
この構造体は USN_RECORD_V3 構造体であり、 構造体の残りの部分はそのレイアウトを使用して解析する必要があります。
4
この構造体は [USN_RECORD_V4 構造体](ns-winioctl-usn_record_v4.md) であり、構造体の残りの部分はそのレイアウトを使用して解析する必要があります。
MinorVersionWORD2+6+6このレコードに対応する変更ジャーナル ソフトウェアのマイナー バージョン番号。たとえば、変更ジャーナル ソフトウェアがバージョン 3.0 の場合、マイナー バージョン番号は 0 です。
FileReferenceNumberFILE_ID_12816+8+8

このレコードが変更を記録する対象となるファイルまたはディレクトリの 128 ビットの序数。

これは、ジャーナル レコードとファイルを関連付けるために任意に割り当てられる値です。

ParentFileReferenceNumberFILE_ID_12816+24+24

このレコードに関連付けられたファイルまたはディレクトリが存在するディレクトリの 128 ビットの序数。

これは、ジャーナル レコードと親ディレクトリを関連付けるために任意に割り当てられる値です。

UsnLONGLONG8+40+40このレコードの USN。
TimeStampLONGLONG8+48+48このレコードの標準的な UTC タイム スタンプ (FILETIME)。64 ビット形式です。
ReasonDWORD4+56+56

このファイルまたはディレクトリのジャーナル レコードにおいて、そのファイルまたはディレクトリが開かれてから 蓄積された変更の理由を示すフラグです。

ファイルまたはディレクトリが閉じられると、USN_REASON_CLOSE フラグが設定された最終的な USN レコードが 生成されます。次の変更 (たとえば、次のオープン操作や削除の後) では、新しい理由フラグのセットを持つ新しいレコードが開始されます。

名前の変更または移動の操作では、2 つの USN レコードが生成されます。1 つは項目の以前の親ディレクトリを記録し、 もう 1 つは新しい親を記録します。

次の表に、設定される可能性のあるフラグを示します。

未使用のビットは予約済みです。
意味
USN_REASON_BASIC_INFO_CHANGE
0x00008000
ユーザーが 1 つ以上のファイルまたはディレクトリの属性 (読み取り専用、隠し、システム、アーカイブ、スパースなどの属性)、 または 1 つ以上のタイム スタンプを変更しました。
USN_REASON_CLOSE
0x80000000
ファイルまたはディレクトリが閉じられました。
USN_REASON_COMPRESSION_CHANGE
0x00020000
ファイルまたはディレクトリの圧縮状態が、圧縮状態から、または圧縮状態へ変更されました。
USN_REASON_DATA_EXTEND
0x00000002
ファイルまたはディレクトリが拡張されました (追加されました)。
USN_REASON_DATA_OVERWRITE
0x00000001
ファイルまたはディレクトリ内のデータが上書きされました。
USN_REASON_DATA_TRUNCATION
0x00000004
ファイルまたはディレクトリが切り詰められました。
USN_REASON_EA_CHANGE
0x00000400
ユーザーがファイルまたはディレクトリの拡張属性を変更しました。
USN_REASON_ENCRYPTION_CHANGE
0x00040000
ファイルまたはディレクトリが暗号化または復号化されました。
USN_REASON_FILE_CREATE
0x00000100
ファイルまたはディレクトリが初めて作成されました。
USN_REASON_FILE_DELETE
0x00000200
ファイルまたはディレクトリが削除されました。
USN_REASON_HARD_LINK_CHANGE
0x00010000
NTFS ファイル システムのハード リンクが、ファイルまたはディレクトリに追加された、あるいは削除されました。

NTFS ファイル システムのハード リンクは、POSIX のハード リンクと同様に、同じファイルまたはディレクトリを参照する 複数のディレクトリ エントリのうちの 1 つです。

USN_REASON_INDEXABLE_CHANGE
0x00004000
ユーザーが FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 属性を変更しました。

つまり、コンテンツのインデックスを作成できるファイルまたはディレクトリから、インデックスを作成できないものへ (またはその逆へ) ユーザーが変更しました。コンテンツのインデックス作成では、選択されたコンテンツのデータベースを 構築することで、データを高速に検索できるようにします。

USN_REASON_INTEGRITY_CHANGE
0x00800000
ユーザーが、指定されたストリームの FILE_ATTRIBUTE_INTEGRITY_STREAM 属性の状態を変更しました。

ReFS ファイル システムでは、整合性ストリームがそのストリームのすべてのデータのチェックサムを保持するため、読み取りまたは書き込み操作の際にファイルの内容を検証できます。

USN_REASON_NAMED_DATA_EXTEND
0x00000020
ファイルの 1 つ以上の名前付きデータ ストリームが拡張されました (追加されました)。
USN_REASON_NAMED_DATA_OVERWRITE
0x00000010
ファイルの 1 つ以上の名前付きデータ ストリーム内のデータが上書きされました。
USN_REASON_NAMED_DATA_TRUNCATION
0x00000040
ファイルの 1 つ以上の名前付きデータ ストリームが切り詰められました。
USN_REASON_OBJECT_ID_CHANGE
0x00080000
ファイルまたはディレクトリのオブジェクト識別子が変更されました。
USN_REASON_RENAME_NEW_NAME
0x00002000
ファイルまたはディレクトリの名前が変更され、 USN_RECORD_V3 構造体内のファイル名が新しい名前です。
USN_REASON_RENAME_OLD_NAME
0x00001000
ファイルまたはディレクトリの名前が変更され、 USN_RECORD_V3 構造体内のファイル名が以前の名前です。
USN_REASON_REPARSE_POINT_CHANGE
0x00100000
ファイルまたはディレクトリに含まれる再解析ポイントが変更された、あるいは再解析ポイントがファイルまたは ディレクトリに追加された、または削除されました。
USN_REASON_SECURITY_CHANGE
0x00000800
ファイルまたはディレクトリへのアクセス権が変更されました。
USN_REASON_STREAM_CHANGE
0x00200000
名前付きストリームがファイルに追加された、ファイルから削除された、または名前付きストリームの名前が変更されました。
USN_REASON_TRANSACTED_CHANGE
0x00400000
指定されたストリームが TxF トランザクションを通じて変更されました。
SourceInfoDWORD4+60+60

変更元に関する追加情報です。 DeviceIoControl 操作の FSCTL_MARK_HANDLE によって設定されます。

スレッドが新しい USN レコードを書き込むとき、直前のレコードのソース情報フラグは、そのスレッドが同じフラグを 設定した場合にのみ引き続き存在します。したがって、ソース情報の構造により、アプリケーションは既知のソース (たとえばウイルス対策フィルター) のみによって設定された USN レコードを除外できます。

次の 2 つの値のいずれかを設定できます。

意味
USN_SOURCE_AUXILIARY_DATA
0x00000002
この操作は、ファイルまたはディレクトリにプライベート データ ストリームを追加します。

例としては、ウイルス検出プログラムがチェックサム情報を追加する場合が挙げられます。ウイルス検出プログラムが 項目を変更すると、システムは USN レコードを生成します。USN_SOURCE_AUXILIARY_DATA は、 その変更がアプリケーションのデータを変更していないことを示します。

USN_SOURCE_DATA_MANAGEMENT
0x00000001
この操作は、オペレーティング システムによって行われたファイルまたはディレクトリの変更に関する情報を提供します。

典型的な用途は、リモート記憶域システムが外部ストレージからローカル ストレージへデータを移動する場合です。 リモート記憶域は階層型記憶域管理ソフトウェアです。このような移動では、通常、少なくとも USN_REASON_DATA_OVERWRITE フラグが USN レコードに追加されます。しかし、ユーザーの視点では データは変更されていません。SourceInfo メンバーで USN_SOURCE_DATA_MANAGEMENT を確認することにより、項目に対して書き込み操作が行われたものの、 データは変更されていないと判断できます。

USN_SOURCE_REPLICATION_MANAGEMENT
0x00000004
この操作は、レプリカ セットの別のメンバーに存在する同一ファイルの内容に一致させるために、 ファイルを変更しています。
USN_SOURCE_CLIENT_REPLICATION_MANAGEMENT
0x00000008
この操作は、クラウドに存在する同一ファイルの内容に一致させるために、クライアント システム上のファイルを変更しています。
SecurityIdDWORD4+64+64このレコードに関連付けられたファイルまたはディレクトリに割り当てられた、一意のセキュリティ識別子。
FileAttributesDWORD4+68+68このレコードに関連付けられたファイルまたはディレクトリの属性で、 GetFileAttributes 関数が返すものと同じです。 ファイルまたはディレクトリに関連付けられたストリームの属性は除外されます。
FileNameLengthWORD2+72+72このレコードに関連付けられたファイルまたはディレクトリの名前の長さ (バイト単位)。この名前は FileName メンバーに格納されます。ファイル名の長さを判定するには、FileName 内で ファイル名を区切る末尾の '\0' に依存せず、このメンバーを使用してください。
FileNameOffsetWORD2+74+74構造体の先頭からの FileName メンバーのオフセット。
FileNameWCHAR2+76+76

このレコードに関連付けられたファイルまたはディレクトリの名前 (Unicode 形式)。このファイル名または ディレクトリ名は可変長です。

FileName を扱うときは、ファイル名に末尾の '\0' 区切り文字が含まれることを前提とせず、 FileNameLength を使用してファイル名の長さを判定してください。

FileName を用いたコンパイル時のポインター演算は行わないでください。代わりに、 FileNameOffset メンバーの値を使用して実行時に必要な計算を行ってください。 そうすることで、将来のバージョンの USN_RECORD_V3 に対してもコードの互換性を保ちやすくなります。

公式ドキュメント

更新シーケンス番号 (USN) 変更ジャーナルのバージョン 3.0 レコードの情報を格納します。バージョン 2.0 のレコードは USN_RECORD_V2 構造体 (USN_RECORD 構造体とも呼ばれます) によって定義されます。

解説(Remarks)

USN_RECORD_V3 を扱う DeviceIoControl 操作から返される出力バッファーでは、すべてのレコードがバッファーの先頭から 64 ビット境界に配置されます。

範囲追跡が有効になっている場合、NTFS は出力として USN_RECORD_V3 レコードのみを生成するように切り替わります。

変更ジャーナルのクライアントに上位互換性の手段を提供するため、Microsoft は変更ジャーナル ソフトウェアの メジャー バージョン番号とマイナー バージョン番号を USN_RECORD_V3 構造体で提供しています。コードではこれらの値を調べ、変更ジャーナル ソフトウェアとの 互換性を判定し、必要であれば非互換性を適切に処理してください。

マイナー バージョン番号の変更は、既存の USN_RECORD_V3 構造体のメンバーが引き続き有効であるものの、最後から 2 番目のメンバーと、 可変長文字列である最後のメンバーとの間に新しいメンバーが追加されている可能性があることを示します。

このような変更を適切に処理するには、最後のメンバーの位置に依存するコンパイル時のポインター演算を行わないでください。 たとえば、そのために C コードの sizeof(USN_RECORD) は信頼できません。代わりに、 RecordLength メンバーを使用して実行時に計算してください。

変更ジャーナル ソフトウェアのメジャー バージョン番号の増加は、 USN_RECORD_V3 構造体に大きな変更が加えられ、現在の定義が信頼できない可能性があることを示します。 変更ジャーナル ソフトウェアのメジャー バージョン番号の変更を検出した場合、コードはその変更ジャーナルを 操作しないようにしてください。

詳細については、 変更ジャーナルの作成、変更、削除を参照してください。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での定義

#include <windows.h>

// FILE_ID_128  (x64 16 / x86 16 バイト)
typedef struct FILE_ID_128 {
    BYTE Identifier[16];
} FILE_ID_128;

// USN_RECORD_V3  (x64 80 / x86 80 バイト)
typedef struct USN_RECORD_V3 {
    DWORD RecordLength;
    WORD MajorVersion;
    WORD MinorVersion;
    FILE_ID_128 FileReferenceNumber;
    FILE_ID_128 ParentFileReferenceNumber;
    LONGLONG Usn;
    LONGLONG TimeStamp;
    DWORD Reason;
    DWORD SourceInfo;
    DWORD SecurityId;
    DWORD FileAttributes;
    WORD FileNameLength;
    WORD FileNameOffset;
    WCHAR FileName[1];
} USN_RECORD_V3;
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct FILE_ID_128
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] Identifier;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct USN_RECORD_V3
{
    public uint RecordLength;
    public ushort MajorVersion;
    public ushort MinorVersion;
    public FILE_ID_128 FileReferenceNumber;
    public FILE_ID_128 ParentFileReferenceNumber;
    public long Usn;
    public long TimeStamp;
    public uint Reason;
    public uint SourceInfo;
    public uint SecurityId;
    public uint FileAttributes;
    public ushort FileNameLength;
    public ushort FileNameOffset;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)] public string FileName;
}
Imports System.Runtime.InteropServices

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure FILE_ID_128
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=16)> Public Identifier() As Byte
End Structure

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure USN_RECORD_V3
    Public RecordLength As UInteger
    Public MajorVersion As UShort
    Public MinorVersion As UShort
    Public FileReferenceNumber As FILE_ID_128
    Public ParentFileReferenceNumber As FILE_ID_128
    Public Usn As Long
    Public TimeStamp As Long
    Public Reason As UInteger
    Public SourceInfo As UInteger
    Public SecurityId As UInteger
    Public FileAttributes As UInteger
    Public FileNameLength As UShort
    Public FileNameOffset As UShort
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1)> Public FileName As String
End Structure
import ctypes
from ctypes import wintypes

class FILE_ID_128(ctypes.Structure):
    _fields_ = [
        ("Identifier", ctypes.c_ubyte * 16),
    ]

class USN_RECORD_V3(ctypes.Structure):
    _fields_ = [
        ("RecordLength", wintypes.DWORD),
        ("MajorVersion", ctypes.c_ushort),
        ("MinorVersion", ctypes.c_ushort),
        ("FileReferenceNumber", FILE_ID_128),
        ("ParentFileReferenceNumber", FILE_ID_128),
        ("Usn", ctypes.c_longlong),
        ("TimeStamp", ctypes.c_longlong),
        ("Reason", wintypes.DWORD),
        ("SourceInfo", wintypes.DWORD),
        ("SecurityId", wintypes.DWORD),
        ("FileAttributes", wintypes.DWORD),
        ("FileNameLength", ctypes.c_ushort),
        ("FileNameOffset", ctypes.c_ushort),
        ("FileName", ctypes.c_wchar * 1),
    ]
#[repr(C)]
pub struct FILE_ID_128 {
    pub Identifier: [u8; 16],
}

#[repr(C)]
pub struct USN_RECORD_V3 {
    pub RecordLength: u32,
    pub MajorVersion: u16,
    pub MinorVersion: u16,
    pub FileReferenceNumber: FILE_ID_128,
    pub ParentFileReferenceNumber: FILE_ID_128,
    pub Usn: i64,
    pub TimeStamp: i64,
    pub Reason: u32,
    pub SourceInfo: u32,
    pub SecurityId: u32,
    pub FileAttributes: u32,
    pub FileNameLength: u16,
    pub FileNameOffset: u16,
    pub FileName: [u16; 1],
}
import "golang.org/x/sys/windows"

type FILE_ID_128 struct {
	Identifier [16]byte
}

type USN_RECORD_V3 struct {
	RecordLength uint32
	MajorVersion uint16
	MinorVersion uint16
	FileReferenceNumber FILE_ID_128
	ParentFileReferenceNumber FILE_ID_128
	Usn int64
	TimeStamp int64
	Reason uint32
	SourceInfo uint32
	SecurityId uint32
	FileAttributes uint32
	FileNameLength uint16
	FileNameOffset uint16
	FileName [1]uint16
}
type
  FILE_ID_128 = record
    Identifier: array[0..15] of Byte;
  end;

  USN_RECORD_V3 = record
    RecordLength: DWORD;
    MajorVersion: Word;
    MinorVersion: Word;
    FileReferenceNumber: FILE_ID_128;
    ParentFileReferenceNumber: FILE_ID_128;
    Usn: Int64;
    TimeStamp: Int64;
    Reason: DWORD;
    SourceInfo: DWORD;
    SecurityId: DWORD;
    FileAttributes: DWORD;
    FileNameLength: Word;
    FileNameOffset: Word;
    FileName: array[0..0] of WideChar;
  end;
const FILE_ID_128 = extern struct {
    Identifier: [16]u8,
};

const USN_RECORD_V3 = extern struct {
    RecordLength: u32,
    MajorVersion: u16,
    MinorVersion: u16,
    FileReferenceNumber: FILE_ID_128,
    ParentFileReferenceNumber: FILE_ID_128,
    Usn: i64,
    TimeStamp: i64,
    Reason: u32,
    SourceInfo: u32,
    SecurityId: u32,
    FileAttributes: u32,
    FileNameLength: u16,
    FileNameOffset: u16,
    FileName: [1]u16,
};
type
  FILE_ID_128 {.bycopy.} = object
    Identifier: array[16, uint8]

  USN_RECORD_V3 {.bycopy.} = object
    RecordLength: uint32
    MajorVersion: uint16
    MinorVersion: uint16
    FileReferenceNumber: FILE_ID_128
    ParentFileReferenceNumber: FILE_ID_128
    Usn: int64
    TimeStamp: int64
    Reason: uint32
    SourceInfo: uint32
    SecurityId: uint32
    FileAttributes: uint32
    FileNameLength: uint16
    FileNameOffset: uint16
    FileName: array[1, uint16]
struct FILE_ID_128
{
    ubyte[16] Identifier;
}

struct USN_RECORD_V3
{
    uint RecordLength;
    ushort MajorVersion;
    ushort MinorVersion;
    FILE_ID_128 FileReferenceNumber;
    FILE_ID_128 ParentFileReferenceNumber;
    long Usn;
    long TimeStamp;
    uint Reason;
    uint SourceInfo;
    uint SecurityId;
    uint FileAttributes;
    ushort FileNameLength;
    ushort FileNameOffset;
    wchar[1] FileName;
}

HSP用 定義

HSP3.7/3.8 は構造体機能が無いため4byte整数配列(dim)+peek/poke で操作(32/64bitでサイズ・位置が異なる場合はタブで分割)。IronHSP は NSTRUCT(#defstruct/stdim/->)で32/64bit共通。

; HSP3.7/3.8 は構造体機能が無いため、4byte整数の配列変数で操作します。(x64 レイアウト)
; USN_RECORD_V3 サイズ: 80 バイト(x64)
dim st, 20    ; 4byte整数×20(構造体サイズ 80 / 4 切り上げ)
; RecordLength : DWORD (+0, 4byte)  st.0 = 値  /  値 = st.0   (lpoke/lpeek も可)
; MajorVersion : WORD (+4, 2byte)  wpoke st,4,値  /  値 = wpeek(st,4)
; MinorVersion : WORD (+6, 2byte)  wpoke st,6,値  /  値 = wpeek(st,6)
; FileReferenceNumber : FILE_ID_128 (+8, 16byte)  varptr(st)+8 を基点に操作(16byte:入れ子/配列)
; ParentFileReferenceNumber : FILE_ID_128 (+24, 16byte)  varptr(st)+24 を基点に操作(16byte:入れ子/配列)
; Usn : LONGLONG (+40, 8byte)  qpoke st,40,値 / qpeek(st,40)  ※IronHSPのみ。3.7/3.8は lpoke st,40,下位 : lpoke st,44,上位
; TimeStamp : LONGLONG (+48, 8byte)  qpoke st,48,値 / qpeek(st,48)  ※IronHSPのみ。3.7/3.8は lpoke st,48,下位 : lpoke st,52,上位
; Reason : DWORD (+56, 4byte)  st.14 = 値  /  値 = st.14   (lpoke/lpeek も可)
; SourceInfo : DWORD (+60, 4byte)  st.15 = 値  /  値 = st.15   (lpoke/lpeek も可)
; SecurityId : DWORD (+64, 4byte)  st.16 = 値  /  値 = st.16   (lpoke/lpeek も可)
; FileAttributes : DWORD (+68, 4byte)  st.17 = 値  /  値 = st.17   (lpoke/lpeek も可)
; FileNameLength : WORD (+72, 2byte)  wpoke st,72,値  /  値 = wpeek(st,72)
; FileNameOffset : WORD (+74, 2byte)  wpoke st,74,値  /  値 = wpeek(st,74)
; FileName : WCHAR (+76, 2byte)  varptr(st)+76 を基点に操作(2byte:入れ子/配列)
; ※4byte境界の整数は添字 st.N(N=オフセット/4)で読み書き可。それ以外は peek/poke 系を使用。
; IronHSP は NSTRUCT(構造体)をサポート。32bit/64bit どちらでも同じコードで動作します。
; ※GUID・入れ子構造体はデフォルト型でないため、依存する #defstruct を先に定義(下記に同梱)。
#defstruct global FILE_ID_128
    #field byte Identifier 16
#endstruct

#defstruct global USN_RECORD_V3
    #field int RecordLength
    #field short MajorVersion
    #field short MinorVersion
    #field FILE_ID_128 FileReferenceNumber
    #field FILE_ID_128 ParentFileReferenceNumber
    #field int64 Usn
    #field int64 TimeStamp
    #field int Reason
    #field int SourceInfo
    #field int SecurityId
    #field int FileAttributes
    #field short FileNameLength
    #field short FileNameOffset
    #field wchar FileName 1
#endstruct

stdim st, USN_RECORD_V3        ; NSTRUCT 変数を確保
st->RecordLength = 100
mes "RecordLength=" + st->RecordLength