PoshUSNJournal.psm1

$ScriptPath = Split-Path $MyInvocation.MyCommand.Path

 Try {
    [void][PoshChJournal]
 } 
 Catch {
    #region Module Builder
    $Domain = [AppDomain]::CurrentDomain
    $DynAssembly = New-Object System.Reflection.AssemblyName('ChJournalAssembly')
    $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) # Only run in memory
    $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('ChJournal', $False)
    #endregion Module Builder

    #region Enums
    #region GetLastErrorEnum Enum
    $EnumBuilder = $ModuleBuilder.DefineEnum('GetLastErrorEnum', 'Public', [int32])
    [void]$EnumBuilder.DefineLiteral('INVALID_HANDLE_VALUE', [int32] -1)
    [void]$EnumBuilder.DefineLiteral('ERROR_SUCCESS', [int32] 0x0)
    [void]$EnumBuilder.DefineLiteral('ERROR_INVALID_FUNCTION', [int32] 0x1)
    [void]$EnumBuilder.DefineLiteral('ERROR_FILE_NOT_FOUND', [int32] 0x2)
    [void]$EnumBuilder.DefineLiteral('ERROR_PATH_NOT_FOUND', [int32] 0x3)
    [void]$EnumBuilder.DefineLiteral('ERROR_TOO_MANY_OPEN_FILES', [int32] 0x4)
    [void]$EnumBuilder.DefineLiteral('ERROR_ACCESS_DENIED', [int32] 0x5)
    [void]$EnumBuilder.DefineLiteral('ERROR_INVALID_HANDLE', [int32] 0x6)
    [void]$EnumBuilder.DefineLiteral('ERROR_INVALID_DATA', [int32] 0xd)
    [void]$EnumBuilder.DefineLiteral('ERROR_HANDLE_EOF', [int32] 0x26)
    [void]$EnumBuilder.DefineLiteral('ERROR_NOT_SUPPORTED', [int32] 0x32)
    [void]$EnumBuilder.DefineLiteral('ERROR_INVALID_PARAMETER', [int32] 0x57)
    [void]$EnumBuilder.DefineLiteral('ERROR_JOURNAL_DELETE_IN_PROGRESS', [int32] 0x49a)
    [void]$EnumBuilder.DefineLiteral('ERROR_JOURNAL_NOT_ACTIVE', [int32] 0x49a)
    [void]$EnumBuilder.DefineLiteral('ERROR_JOURNAL_ENTRY_DELETED', [int32] 0x49d)
    [void]$EnumBuilder.DefineLiteral('ERROR_INVALID_USER_BUFFER', [int32] 0x6f8)
    [void]$EnumBuilder.CreateType()
    #endregion GetLastErrorEnum Enum
    #region USN_REASON Enum
    $EnumBuilder = $ModuleBuilder.DefineEnum('USN_REASON', 'Public', [int32])
    [void]$EnumBuilder.DefineLiteral('USN_REASON_DATA_OVERWRITE', [int32] 0x00000001)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_DATA_EXTEND', [int32] 0x00000002)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_DATA_TRUNCATION', [int32] 0x00000004)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_NAMED_DATA_OVERWRITE', [int32] 0x00000010)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_NAMED_DATA_EXTEND', [int32] 0x00000020)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_NAMED_DATA_TRUNCATION', [int32] 0x00000040)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_FILE_CREATE', [int32] 0x00000100)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_FILE_DELETE', [int32] 0x00000200)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_EA_CHANGE', [int32] 0x00000400)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_SECURITY_CHANGE', [int32] 0x00000800)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_RENAME_OLD_NAME', [int32] 0x00001000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_RENAME_NEW_NAME', [int32] 0x00002000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_INDEXABLE_CHANGE', [int32] 0x00004000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_BASIC_INFO_CHANGE', [int32] 0x00008000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_HARD_LINK_CHANGE', [int32] 0x00010000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_COMPRESSION_CHANGE', [int32] 0x00020000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_ENCRYPTION_CHANGE', [int32] 0x00040000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_OBJECT_ID_CHANGE', [int32] 0x00080000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_REPARSE_POINT_CHANGE', [int32] 0x00100000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_STREAM_CHANGE', [int32] 0x00200000)  
    [void]$EnumBuilder.DefineLiteral('USN_REASON_CLOSE', [int32] 0x80000000)
    [void]$EnumBuilder.CreateType()
    #endregion USN_REASON Enum
    #region EMethod Enum
    $EnumBuilder = $ModuleBuilder.DefineEnum('EMethod', 'Public', [uint32])
    [void]$EnumBuilder.DefineLiteral('Buffered', [uint32] 0x0)
    [void]$EnumBuilder.DefineLiteral('InDirect', [uint32] 0x1)
    [void]$EnumBuilder.DefineLiteral('OutDirect', [uint32] 0x2)
    [void]$EnumBuilder.DefineLiteral('Neither', [uint32] 0x3)
    [void]$EnumBuilder.CreateType()
    #endregion EMethod Enum
    #region EFileDevice Enum
    $EnumBuilder = $ModuleBuilder.DefineEnum('EFileDevice', 'Public', [uint32])
    [void]$EnumBuilder.DefineLiteral('DiskFileSystem', [uint32] 0x8)
    [void]$EnumBuilder.DefineLiteral('FileSystem', [uint32] 0x9)
    [void]$EnumBuilder.CreateType()
    #endregion EFileDevice Enum
    #region EIOControlCode Enum
    $EnumBuilder = $ModuleBuilder.DefineEnum('EIOControlCode', 'Public', [uint32])
    [void]$EnumBuilder.DefineLiteral('FSCTL_QUERY_USN_JOURNAL', [uint32] 0x900f4)
    [void]$EnumBuilder.DefineLiteral('FSCTL_READ_USN_JOURNAL', [uint32] 0x900bb)
    [void]$EnumBuilder.DefineLiteral('FSCTL_ENUM_USN_DATA', [uint32] 0x900f4)
    [void]$EnumBuilder.DefineLiteral('FSCTL_CREATE_USN_JOURNAL', [uint32] 0x900e7)
    [void]$EnumBuilder.DefineLiteral('FSCTL_DELETE_USN_JOURNAL', [uint32] 0x900f8)
    [void]$EnumBuilder.CreateType()
    #endregion EIOControlCode Enum
    #region FILE_INFORMATION_CLASS Enum
    $EnumBuilder = $ModuleBuilder.DefineEnum('FILE_INFORMATION_CLASS', 'Public', [int32])
    [void]$EnumBuilder.DefineLiteral('FileDirectoryInformation', [int32] 1)
    [void]$EnumBuilder.DefineLiteral('FileFullDirectoryInformation', [int32] 2)
    [void]$EnumBuilder.DefineLiteral('FileBothDirectoryInformation', [int32] 3)
    [void]$EnumBuilder.DefineLiteral('FileBasicInformation', [int32] 4)
    [void]$EnumBuilder.DefineLiteral('FileStandardInformation', [int32] 5)
    [void]$EnumBuilder.DefineLiteral('FileInternalInformation', [int32] 6)
    [void]$EnumBuilder.DefineLiteral('FileEaInformation', [int32] 7)
    [void]$EnumBuilder.DefineLiteral('FileAccessInformation', [int32] 8)
    [void]$EnumBuilder.DefineLiteral('FileNameInformation', [int32] 9)
    [void]$EnumBuilder.DefineLiteral('FileRenameInformation', [int32] 10)
    [void]$EnumBuilder.DefineLiteral('FileLinkInformation', [int32] 11)
    [void]$EnumBuilder.DefineLiteral('FileNamesInformation', [int32] 12)
    [void]$EnumBuilder.DefineLiteral('FileDispositionInformation', [int32] 13)
    [void]$EnumBuilder.DefineLiteral('FilePositionInformation', [int32] 14)
    [void]$EnumBuilder.DefineLiteral('FileFullEaInformation', [int32] 15)
    [void]$EnumBuilder.DefineLiteral('FileModeInformation', [int32] 16)
    [void]$EnumBuilder.DefineLiteral('FileAlignmentInformation', [int32] 17)
    [void]$EnumBuilder.DefineLiteral('FileAllInformation', [int32] 18)
    [void]$EnumBuilder.DefineLiteral('FileAllocationInformation', [int32] 19)
    [void]$EnumBuilder.DefineLiteral('FileEndOfFileInformation', [int32] 20)
    [void]$EnumBuilder.DefineLiteral('FileAlternateNameInformation', [int32] 21)
    [void]$EnumBuilder.DefineLiteral('FileStreamInformation', [int32] 22)
    [void]$EnumBuilder.DefineLiteral('FilePipeInformation', [int32] 23)
    [void]$EnumBuilder.DefineLiteral('FilePipeLocalInformation', [int32] 24)
    [void]$EnumBuilder.DefineLiteral('FilePipeRemoteInformation', [int32] 25)
    [void]$EnumBuilder.DefineLiteral('FileMailslotQueryInformation', [int32] 26)
    [void]$EnumBuilder.DefineLiteral('FileMailslotSetInformation', [int32] 27)
    [void]$EnumBuilder.DefineLiteral('FileCompressionInformation', [int32] 28)
    [void]$EnumBuilder.DefineLiteral('FileObjectIdInformation', [int32] 29)
    [void]$EnumBuilder.DefineLiteral('FileCompletionInformation', [int32] 30)
    [void]$EnumBuilder.DefineLiteral('FileMoveClusterInformation', [int32] 31)
    [void]$EnumBuilder.DefineLiteral('FileQuotaInformation', [int32] 32)
    [void]$EnumBuilder.DefineLiteral('FileReparsePointInformation', [int32] 33)
    [void]$EnumBuilder.DefineLiteral('FileNetworkOpenInformation', [int32] 34)
    [void]$EnumBuilder.DefineLiteral('FileAttributeTagInformation', [int32] 35)
    [void]$EnumBuilder.DefineLiteral('FileTrackingInformation', [int32] 36)
    [void]$EnumBuilder.DefineLiteral('FileIdBothDirectoryInformation', [int32] 37)
    [void]$EnumBuilder.DefineLiteral('FileIdFullDirectoryInformation', [int32] 38)
    [void]$EnumBuilder.DefineLiteral('FileValidDataLengthInformation', [int32] 39)
    [void]$EnumBuilder.DefineLiteral('FileShortNameInformation', [int32] 40)
    [void]$EnumBuilder.DefineLiteral('FileHardLinkInformation', [int32] 46)
    [void]$EnumBuilder.CreateType()
    #endregion FILE_INFORMATION_CLASS Enum
    #region UsnJournalDeleteFlags Enum
    $EnumBuilder = $ModuleBuilder.DefineEnum('UsnJournalDeleteFlags', 'Public', [uint32])
    [void]$EnumBuilder.DefineLiteral('USN_DELETE_FLAG_DELETE', [uint32] 0x1) 
    [void]$EnumBuilder.DefineLiteral('USN_DELETE_FLAG_NOTIFY', [uint32] 0x2)
    [void]$EnumBuilder.CreateType()
    #endregion UsnJournalDeleteFlags Enum
    #endregion Enums

    #region Structs
    $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
    #region USN_JOURNAL_DATA STRUCT
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('USN_JOURNAL_DATA', $Attributes, [System.ValueType], 8)
    [void]$STRUCT_TypeBuilder.DefineField('UsnJournalID', [long], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('FirstUsn', [long], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('NextUsn', [long], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('LowestValidUsn', [long], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('MaxUsn', [long], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('MaximumSize', [long], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('AllocationDelta', [long], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion USN_JOURNAL_DATA STRUCT
    #region READ_USN_JOURNAL_DATA STRUCT
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('READ_USN_JOURNAL_DATA', $Attributes, [System.ValueType], 8)
    [void]$STRUCT_TypeBuilder.DefineField('StartUsn', [int64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('ReasonMask', [int32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('ReturnOnlyOnClose', [int32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('Timeout', [long], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('BytesToWaitFor', [long], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('UsnJournalID', [long], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion READ_USN_JOURNAL_DATA STRUCT
    #region IO_STATUS_BLOCK STRUCT
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('IO_STATUS_BLOCK', $Attributes, [System.ValueType], 1, 0x10)
    [void]$STRUCT_TypeBuilder.DefineField('status', [UInt64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('information', [UInt64], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion IO_STATUS_BLOCK STRUCT
    #region OBJECT_ATTRIBUTES STRUCT
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('OBJECT_ATTRIBUTES', $Attributes, [System.ValueType], 8)
    [void]$STRUCT_TypeBuilder.DefineField('Length', [int32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('RootDirectory', [intptr], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('ObjectName', [intptr], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('Attributes', [int32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('SecurityDescriptor', [intptr], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('SecurityQualityOfService', [intptr], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion OBJECT_ATTRIBUTES STRUCT
    #region UNICODE_STRING STRUCT
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('UNICODE_STRING', $Attributes, [System.ValueType], 8)
    [void]$STRUCT_TypeBuilder.DefineField('Length', [int16], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('MaximumLength', [int16], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('Buffer', [intptr], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion UNICODE_STRING STRUCT
    #region POINT STRUCT
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('POINT', $Attributes, [System.ValueType], 8)
    [void]$STRUCT_TypeBuilder.DefineField('X', [int], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('Y', [int], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion POINT STRUCT
    #region USN_RECORD STRUCT
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('USN_RECORD', $Attributes, [System.ValueType], 8)
    [void]$STRUCT_TypeBuilder.DefineField('RecordLength', [uint32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('MajorVersion', [uint16], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('MinorVersion', [uint16], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('FileReferenceNumber', [uint64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('ParentFileReferenceNumber', [uint64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('Usn', [int64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('TimeStamp', [int64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('Reason', [uint32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('SourceInfo', [uint32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('SecurityId', [uint32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('FileAttributes', [uint32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('FileNameLength', [uint16], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('FileNameOffset', [uint16], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion USN_RECORD STRUCT
    #region CREATE_USN_JOURNAL_DATA
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('CREATE_USN_JOURNAL_DATA', $Attributes, [System.ValueType], 8)
    [void]$STRUCT_TypeBuilder.DefineField('MaximumSize', [uint64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('AllocationData', [uint64], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion CREATE_USN_JOURNAL_DATA
    #region DELETE_USN_JOURNAL_DATA
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('DELETE_USN_JOURNAL_DATA', $Attributes, [System.ValueType], 8)
    [void]$STRUCT_TypeBuilder.DefineField('UsnJournalID', [uint64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('DeleteFlags', [uint32], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('Reserved', [uint32], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion DELETE_USN_JOURNAL_DATA
    #region MFT_ENUM_DATA
    $STRUCT_TypeBuilder = $ModuleBuilder.DefineType('MFT_ENUM_DATA', $Attributes, [System.ValueType], 8)
    [void]$STRUCT_TypeBuilder.DefineField('StartFileReferenceNumber', [uint64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('LowUsn', [uint64], 'Public')
    [void]$STRUCT_TypeBuilder.DefineField('HighUsn', [uint64], 'Public')
    [void]$STRUCT_TypeBuilder.CreateType()
    #endregion MFT_ENUM_DATA
    #endregion Structs

    #region Initialize Type Builder
    $TypeBuilder = $ModuleBuilder.DefineType('PoshChJournal', 'Public, Class')
    #endregion Initialize Type Builder

    #region Methods
    #region CreateFile METHOD
    $PInvokeMethod = $TypeBuilder.DefineMethod(
        'CreateFile', #Method Name
        [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes
        [IntPtr ], #Method Return Type
        [Type[]] @(
            [string],                   # Filename
            [System.IO.FileAccess],     # Access
            [System.IO.FileShare],      # Share
            [intptr],                   # Security attributes
            [System.IO.FileMode],       # Creation Disposition
            [System.IO.FileAttributes], # Flags and Attributes
            [intptr]                    # Template File
        ) #Method Parameters
    )
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
    $FieldArray = [Reflection.FieldInfo[]] @(
        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
        [Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling')
    )

    $FieldValueArray = [Object[]] @(
        'CreateFile', #CASE SENSITIVE!!
        $True,
        $False
    )

    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(
        $DllImportConstructor,
        @('kernel32.dll'),
        $FieldArray,
        $FieldValueArray
    )

    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
    #endregion CreateFile METHOD
    #region NtCreateFile METHOD

    $PInvokeMethod = $TypeBuilder.DefineMethod(
        'NtCreateFile', #Method Name
        [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes
        [int], #Method Return Type
        [Type[]] @(
            [intptr].MakeByRefType(), # File Handle
            [System.IO.FileAccess],                       # Access
            [OBJECT_ATTRIBUTES].MakeByRefType(),          # Object Attributes
            [IO_STATUS_BLOCK].MakeByRefType(),            # IO Status
            [long].MakeByRefType(),                       # Allocation Size
            [Uint32],                                     # File Attributes
            [System.IO.FileShare],                        # Share
            [Uint32],                                     # CreateDisposition
            [Uint32],                                     # CreateOptions
            [IntPtr],                                     # EABuffer
            [Uint32]                                       # EALength
        ) #Method Parameters
    )
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
    $FieldArray = [Reflection.FieldInfo[]] @(
        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
        [Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling')
    )

    $FieldValueArray = [Object[]] @(
        'NtCreateFile', #CASE SENSITIVE!!
        $True,
        $False
    )

    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(
        $DllImportConstructor,
        @('ntdll.dll'),
        $FieldArray,
        $FieldValueArray
    )

    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
    #endregion NtCreateFile METHOD
    #region NtQueryInformationFile METHOD
    $PInvokeMethod = $TypeBuilder.DefineMethod(
        'NtQueryInformationFile', #Method Name
        [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes
        [intptr], #Method Return Type
        [Type[]] @(
            [intptr],                          # File Handle
            [IO_STATUS_BLOCK].MakeByRefType(), # IO Status Block
            [intptr],                          # pInfo Block
            [Uint32],                          # Length
            [FILE_INFORMATION_CLASS]           # FileInformation
        ) #Method Parameters
    )
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
    $FieldArray = [Reflection.FieldInfo[]] @(
        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
        [Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling')
    )

    $FieldValueArray = [Object[]] @(
        'NtQueryInformationFile', #CASE SENSITIVE!!
        $True,
        $False
    )

    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(
        $DllImportConstructor,
        @('ntdll.dll'),
        $FieldArray,
        $FieldValueArray
    )

    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
    #endregion NtQueryInformationFile METHOD
    #region DeviceIoControl METHODs
    $PInvokeMethod = $TypeBuilder.DefineMethod(
        'DeviceIoControl', #Method Name
        [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes
        [bool ], #Method Return Type
        [Type[]] @(
            [intptr],                           # hDevice
            [uint32],                           # IOControlCode
            [long].MakeByRefType(),             # InBuffer
            [int],                              # InBufferSize
            [USN_JOURNAL_DATA].MakeByRefType(),             # OutBuffer
            [int],                              # OutBufferSize
            [int].MakeByRefType(),              # lpBytesReturned
            [intptr] # lpOverlapped
        ) #Method Parameters
    )
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
    $FieldArray = [Reflection.FieldInfo[]] @(
        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
        [Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling')
    )

    $FieldValueArray = [Object[]] @(
        'DeviceIoControl', #CASE SENSITIVE!!
        $True,
        $False
    )

    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(
        $DllImportConstructor,
        @('kernel32.dll'),
        $FieldArray,
        $FieldValueArray
    )

    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)

    $PInvokeMethod = $TypeBuilder.DefineMethod(
        'DeviceIoControl', #Method Name
        [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes
        [bool ], #Method Return Type
        [Type[]] @(
            [intptr],                           # hDevice
            [uint32],                           # IOControlCode
            [intptr],                             # InBuffer
            [int],                              # InBufferSize
            [intptr],                           # OutBuffer
            [int],                              # OutBufferSize
            [int].MakeByRefType(),              # lpBytesReturned
            [intptr] # lpOverlapped
        ) #Method Parameters
    )
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
    $FieldArray = [Reflection.FieldInfo[]] @(
        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
        [Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling')
    )

    $FieldValueArray = [Object[]] @(
        'DeviceIoControl', #CASE SENSITIVE!!
        $True,
        $False
    )

    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(
        $DllImportConstructor,
        @('kernel32.dll'),
        $FieldArray,
        $FieldValueArray
    )

    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
    #endregion DeviceIoControl METHODs
    #region CloseHandle METHOD
    $PInvokeMethod = $TypeBuilder.DefineMethod(
        'CloseHandle', #Method Name
        [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes
        [bool ], #Method Return Type
        [Type[]] @(
            [intptr] # Handle
        ) #Method Parameters
    )
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
    $FieldArray = [Reflection.FieldInfo[]] @(
        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
        [Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling')
    )

    $FieldValueArray = [Object[]] @(
        'CloseHandle', #CASE SENSITIVE!!
        $True,
        $False
    )

    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(
        $DllImportConstructor,
        @('kernel32.dll'),
        $FieldArray,
        $FieldValueArray
    )

    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
    #endregion CloseHandle METHOD
    #region ZeroMemory
    $PInvokeMethod = $TypeBuilder.DefineMethod(
        'ZeroMemory', #Method Name
        [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes
        [bool ], #Method Return Type
        [Type[]] @(
            [intptr], # Destination
            [intptr]  # Size
        ) #Method Parameters
    )
    $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
    $FieldArray = [Reflection.FieldInfo[]] @(
        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
        [Runtime.InteropServices.DllImportAttribute].GetField('ExactSpelling')
    )

    $FieldValueArray = [Object[]] @(
        'RtlZeroMemory', #CASE SENSITIVE!!
        $True,
        $False
    )

    $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(
        $DllImportConstructor,
        @('kernel32.dll'),
        $FieldArray,
        $FieldValueArray
    )

    $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
    #endregion ZeroMemory
    #endregion Methods

    #region Create Type
    [void]$TypeBuilder.CreateType()
    #endregion Create Type
}

#region Private Helper Functions
Function ConvertToUSNReason {
    [cmdletbinding()]
    Param(
        $ReasonCode
    )
    $List = New-Object System.Collections.ArrayList
    Switch ($ReasonCode) {
        ($ReasonCode -BOR 0x00000001) {[void]$List.Add('USN_REASON_DATA_OVERWRITE')}
        ($ReasonCode -BOR 0x00000002) {[void]$List.Add('USN_REASON_DATA_EXTEND')}
        ($ReasonCode -BOR 0x00000004) {[void]$List.Add('USN_REASON_DATA_TRUNCATION')}
        ($ReasonCode -BOR 0x00000010) {[void]$List.Add('USN_REASON_NAMED_DATA_OVERWRITE')}
        ($ReasonCode -BOR 0x00000020) {[void]$List.Add('USN_REASON_NAMED_DATA_EXTEND')}
        ($ReasonCode -BOR 0x00000040) {[void]$List.Add('USN_REASON_NAMED_DATA_TRUNCATION')}
        ($ReasonCode -BOR 0x00000100) {[void]$List.Add('USN_REASON_FILE_CREATE')}
        ($ReasonCode -BOR 0x00000200) {[void]$List.Add('USN_REASON_FILE_DELETE')}
        ($ReasonCode -BOR 0x00000400) {[void]$List.Add('USN_REASON_EA_CHANGE')}
        ($ReasonCode -BOR 0x00000800) {[void]$List.Add('USN_REASON_SECURITY_CHANGE')}
        ($ReasonCode -BOR 0x00001000) {[void]$List.Add('USN_REASON_RENAME_OLD_NAME')}
        ($ReasonCode -BOR 0x00002000) {[void]$List.Add('USN_REASON_RENAME_NEW_NAME')}
        ($ReasonCode -BOR 0x00004000) {[void]$List.Add('USN_REASON_INDEXABLE_CHANGE')}
        ($ReasonCode -BOR 0x00008000) {[void]$List.Add('USN_REASON_BASIC_INFO_CHANGE')}
        ($ReasonCode -BOR 0x00010000) {[void]$List.Add('USN_REASON_HARD_LINK_CHANGE')}
        ($ReasonCode -BOR 0x00020000) {[void]$List.Add('USN_REASON_COMPRESSION_CHANGE')}
        ($ReasonCode -BOR 0x00040000) {[void]$List.Add('USN_REASON_ENCRYPTION_CHANGE')}
        ($ReasonCode -BOR 0x00080000) {[void]$List.Add('USN_REASON_OBJECT_ID_CHANGE')}
        ($ReasonCode -BOR 0x00100000) {[void]$List.Add('USN_REASON_REPARSE_POINT_CHANGE')}
        ($ReasonCode -BOR 0x00200000) {[void]$List.Add('USN_REASON_STREAM_CHANGE')}
        ($ReasonCode -BOR 0x80000000) {[void]$List.Add('USN_REASON_CLOSE')}
    }
    $List -join ', '
} 
Function NewUsnEntry {
    [cmdletbinding()]
    Param (
        [intptr]$UsnRecord,
        [string]$DriveLetter,
        [IntPtr]$VolumeHandle
    )
    #region Constants
    $FILE_ATTRIBUTE_DIRECTORY = 0x00000010
    #endregion Constants

    #region Marshal to Struct
    $USN_RECORD = [System.Runtime.InteropServices.Marshal]::PtrToStructure($UsnRecord, [type][USN_RECORD])
    #endregion Marshal to Struct

    #region Data Conversions
    $Name = [System.Runtime.InteropServices.Marshal]::PtrToStringUni([intptr](
        $UsnRecord.ToInt64()+$USN_RECORD.FileNameOffset),
        ($USN_RECORD.FileNameLength/2)
    )
    #endregion Data Conversions

    #region Object Creation
    If (($USN_RECORD.FileAttributes -BAND $FILE_ATTRIBUTE_DIRECTORY) -eq 0) {
        $IsFile = $True
        $IsFolder = $False
    } Else {
        $IsFile = $False
        $IsFolder = $True    
    }
    [pscustomobject]@{
        FileName = $Name
        FullName = GetFilePath -PFileRefNumber $USN_RECORD.ParentFileReferenceNumber -VolumeHandle $VolumeHandle -DriveLetter $DriveLetter -File $Name
        TimeStamp = [DateTime]::FromFileTime($USN_RECORD.TimeStamp)
        Reason = ConvertToUsnReason $USN_RECORD.Reason
        RecordLength = $USN_RECORD.RecordLength
        FileReferenceNumber = $USN_RECORD.FileReferenceNumber
        ParentFileReferenceNumber = $USN_RECORD.ParentFileReferenceNumber
        USN = $USN_RECORD.USN
        FileAttributes = [System.IO.FileAttributes]($USN_RECORD.FileAttributes)
        IsFile = $IsFile
        IsDirectory = $IsFolder
    }
    #endregion Object Creation
}
Function OpenUSNJournal {
    Param ($DriveLetter = 'c:')

    $FileName = "\\.\$DriveLetter"
    $Access = [System.IO.FileAccess]::Read -BOR [System.IO.FileAccess]::Write
    $ShareAccess = [System.IO.FileShare]::Read -BOR [System.IO.FileShare]::Write
    $FileMode = [System.IO.FileMode]::Open
    $VolumeHandle = [PoshChJournal]::CreateFile(
        $FileName,
        $Access,
        $ShareAccess,
        [intptr]::Zero,
        $FileMode,
        0,
        [intptr]::Zero
    )
    If ($VolumeHandle -eq -1) {
        Write-Warning ("CreateFile failed: 0x{0:x}" -f [System.Runtime.InteropServices.Marshal]::GetHRForLastWin32Error())
    } Else {
        $VolumeHandle
    }
}
Function GetFilePath {
    Param (
        [int64]$PFileRefNumber, 
        [IntPtr]$VolumeHandle,
        [string]$DriveLetter,
        [string]$File
    )

    $OBJ_CASE_INSENSITIVE = 0x40
    $FILE_OPEN = 0x1
    $FILE_OPEN_FOR_BACKUP_INTENT = 0x4000
    $FILE_OPEN_BY_FILE_ID = 0x2000

    [long]$AllocationSize = 0
    $UnicodeString = New-Object UNICODE_STRING
    $ObjectAttributes = New-Object OBJECT_ATTRIBUTES
    $IoStatusBlock = New-Object IO_STATUS_BLOCK
    $FileHandle = [intptr]::Zero

    $Buffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4096)
    $RefPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(8)
    $ObjectAttributeSize = [System.Runtime.InteropServices.Marshal]::SizeOf($ObjectAttributes)
    $ObjAttIntPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($ObjectAttributeSize)

    [void][System.Runtime.InteropServices.Marshal]::WriteInt64($RefPtr, $PFileRefNumber)
    $UnicodeString.Length = 8
    $UnicodeString.MaximumLength = 8
    $UnicodeString.Buffer = $RefPtr

    [void][System.Runtime.InteropServices.Marshal]::StructureToPtr($UnicodeString, $ObjAttIntPtr, $True)

    $ObjectAttributes.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($ObjectAttributes)
    $ObjectAttributes.ObjectName = $ObjAttIntPtr
    $ObjectAttributes.RootDirectory = $VolumeHandle
    $ObjectAttributes.Attributes = $OBJ_CASE_INSENSITIVE

    $Access = [System.IO.FileAccess]::Read
    $ShareAccess = [System.IO.FileShare]::Read -BOR [System.IO.FileShare]::Write
    $FileMode = [System.IO.FileMode]::Open
    $Return = [PoshChJournal]::NtCreateFile(
        [ref]$FileHandle,
        $Access,
        [ref]$ObjectAttributes,
        [ref]$IoStatusBlock,
        [ref]$AllocationSize,
        0,
        $ShareAccess,
        $FILE_OPEN,
        ($FILE_OPEN_FOR_BACKUP_INTENT -BOR $FILE_OPEN_BY_FILE_ID),
        [intptr]::Zero,
        0
    )
    If ($Return -eq 0) {
        $Return = [PoshChJournal]::NTQueryInformationFile(
            $FileHandle,
            [ref]$IoStatusBlock,
            $Buffer,
            4096,
            [FILE_INFORMATION_CLASS]::FileNameInformation
        )
        If ($Return -eq 0) {
            $NameLength = [System.Runtime.InteropServices.Marshal]::ReadInt32($Buffer,0)
            $BufferPtr = New-Object IntPtr -ArgumentList ($Buffer.ToInt64()+4)
            $Path = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($BufferPtr,($NameLength/2))
            "{0}{1}\{2}" -f $DriveLetter,$Path,$File
        }
    }
    [void][PoshChJournal]::CloseHandle($FileHandle)
    [void][System.Runtime.InteropServices.Marshal]::FreeHGlobal($Buffer)
    [void][System.Runtime.InteropServices.Marshal]::FreeHGlobal($ObjectAttributeSize)
    [void][System.Runtime.InteropServices.Marshal]::FreeHGlobal($RefPtr)
}
#endregion Private Helper Functions

#region Load Functions
Try {
    Get-ChildItem "$ScriptPath\Scripts" -Filter *.ps1 | Select -Expand FullName | ForEach {
        $Function = Split-Path $_ -Leaf
        . $_
    }
} Catch {
    Write-Warning ("{0}: {1}" -f $Function,$_.Exception.Message)
    Continue
}
#endregion Load Functions

#region Aliases
New-Alias -Name guj -Value Get-UsnJournal
New-Alias -Name guje -Value Get-UsnJournalEntry
#endregion Aliases

#region Format and Type Data
Update-FormatData "$ScriptPath\TypeData\PoshUsnJournal.Format.ps1xml"
#endregion Format and Type Data

Export-ModuleMember -Function *-USN* -Alias *