#------------------------------------------------------------------------------
# File:         Microsoft.pm
#
# Description:  Definitions for custom Microsoft tags
#
# Revisions:    2010/10/01 - P. Harvey Created
#               2011/10/05 - PH Added ProcessXtra()
#
# References:   1) http://research.microsoft.com/en-us/um/redmond/groups/ivm/hdview/hdmetadataspec.htm
#------------------------------------------------------------------------------

package Image::ExifTool::Microsoft;

use strict;
use vars qw($VERSION);
use Image::ExifTool qw(:DataAccess :Utils);
use Image::ExifTool::XMP;

$VERSION = '1.20';

sub ProcessXtra($$$);

# tags written by Microsoft HDView (ref 1)
%Image::ExifTool::Microsoft::Stitch = (
    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
    WRITABLE => 1,
    FORMAT => 'float',
    FIRST_ENTRY => 0,
    GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
    NOTES => q{
        Information found in the Microsoft custom EXIF tag 0x4748, as written by
        Windows Live Photo Gallery.
    },
    0 => {
        Name => 'PanoramicStitchVersion',
        Format => 'int32u',
    },
    1 => {
        Name => 'PanoramicStitchCameraMotion',
        Format => 'int32u',
        PrintConv => {
            2 => 'Rigid Scale',
            3 => 'Affine',
            4 => '3D Rotation',
            5 => 'Homography',
        },
    },
    2 => {
        Name => 'PanoramicStitchMapType',
        Format => 'int32u',
        PrintConv => {
            0 => 'Perspective',
            1 => 'Horizontal Cylindrical',
            2 => 'Horizontal Spherical',
            257 => 'Vertical Cylindrical',
            258 => 'Vertical Spherical',
        },
    },
    3 => 'PanoramicStitchTheta0',
    4 => 'PanoramicStitchTheta1',
    5 => 'PanoramicStitchPhi0',
    6 => 'PanoramicStitchPhi1',
);

# Microsoft Photo schema properties (MicrosoftPhoto) (ref PH)
%Image::ExifTool::Microsoft::XMP = (
    %Image::ExifTool::XMP::xmpTableDefaults,
    GROUPS => { 0 => 'XMP', 1 => 'XMP-microsoft', 2 => 'Image' },
    NAMESPACE => 'MicrosoftPhoto',
    TABLE_DESC => 'XMP Microsoft',
    VARS => { NO_ID => 1 },
    NOTES => q{
        Microsoft Photo 1.0 schema XMP tags.  This is likely not a complete list,
        but represents tags which have been observed in sample images.  The actual
        namespace prefix is "MicrosoftPhoto", but ExifTool shortens this in the
        family 1 group name.
    },
    CameraSerialNumber => { },
    DateAcquired       => { Groups => { 2 => 'Time' }, %Image::ExifTool::XMP::dateTimeInfo },
    FlashManufacturer  => { },
    FlashModel         => { },
    LastKeywordIPTC    => { List => 'Bag' },
    LastKeywordXMP     => { List => 'Bag' },
    LensManufacturer   => { },
    LensModel          => { Avoid => 1 },
    Rating => {
        Name => 'RatingPercent',
        Notes => q{
            XMP-xmp:Rating values of 1,2,3,4 and 5 stars correspond to RatingPercent
            values of 1,25,50,75 and 99 respectively
        },
    },
    CreatorAppId             => { Name => 'CreatorAppID' },
    CreatorOpenWithUIOptions => { },
    ItemSubType              => { },
);

# Microsoft Photo 1.1 schema properties (MP1 - written as 'prefix0' by MSPhoto) (ref PH)
%Image::ExifTool::Microsoft::MP1 = (
    %Image::ExifTool::XMP::xmpTableDefaults,
    GROUPS => { 0 => 'XMP', 1 => 'XMP-MP1', 2 => 'Image' },
    NAMESPACE => 'MP1',
    TABLE_DESC => 'XMP Microsoft Photo',
    VARS => { NO_ID => 1 },
    NOTES => q{
        Microsoft Photo 1.1 schema XMP tags which have been observed.
    },
    PanoramicStitchCameraMotion => {
        PrintConv => {
            'RigidScale' => 'Rigid Scale',
            'Affine'     => 'Affine',
            '3DRotation' => '3D Rotation',
            'Homography' => 'Homography',
        },
    },
    PanoramicStitchMapType => {
        PrintConv => {
            'Perspective'            => 'Perspective',
            'Horizontal-Cylindrical' => 'Horizontal Cylindrical',
            'Horizontal-Spherical'   => 'Horizontal Spherical',
            'Vertical-Cylindrical'   => 'Vertical Cylindrical',
            'Vertical-Spherical'     => 'Vertical Spherical',
        },
    },
    PanoramicStitchPhi0   => { Writable => 'real' },
    PanoramicStitchPhi1   => { Writable => 'real' },
    PanoramicStitchTheta0 => { Writable => 'real' },
    PanoramicStitchTheta1 => { Writable => 'real' },
    WhiteBalance0         => { Writable => 'real' },
    WhiteBalance1         => { Writable => 'real' },
    WhiteBalance2         => { Writable => 'real' },
    Brightness            => { Avoid => 1 },
    Contrast              => { Avoid => 1 },
    CameraModelID         => { Avoid => 1 },
    ExposureCompensation  => { Avoid => 1 },
    PipelineVersion       => { },
    StreamType            => { },
);

# Microsoft Photo 1.2 schema properties (MP) (ref PH)
# (also ref http://msdn.microsoft.com/en-us/library/windows/desktop/ee719905(v=vs.85).aspx)
my %sRegions = (
    STRUCT_NAME => 'Microsoft Regions',
    NAMESPACE   => 'MPReg',
    NOTES => q{
        Note that PersonLiveIdCID element is called PersonLiveCID according to the
        Microsoft specification, but in practice their software actually writes
        PersonLiveIdCID, so ExifTool uses this too.
    },
    Rectangle         => { },
    PersonDisplayName => { },
    PersonEmailDigest => { },
    PersonLiveIdCID   => { },  # (see https://exiftool.org/forum/index.php?topic=4274.msg20368#msg20368)
    PersonSourceID    => { },
);
%Image::ExifTool::Microsoft::MP = (
    %Image::ExifTool::XMP::xmpTableDefaults,
    GROUPS => { 0 => 'XMP', 1 => 'XMP-MP', 2 => 'Image' },
    NAMESPACE => 'MP',
    TABLE_DESC => 'XMP Microsoft Photo',
    VARS => { NO_ID => 1 },
    NOTES => q{
        Microsoft Photo 1.2 schema XMP tags which have been observed.
    },
    RegionInfo => {
        Name => 'RegionInfoMP',
        Struct => {
            STRUCT_NAME => 'Microsoft RegionInfo',
            NAMESPACE   => 'MPRI',
            Regions   => { Struct => \%sRegions, List => 'Bag' },
            DateRegionsValid => {
                Writable => 'date',
                Shift => 'Time',
                Groups => { 2 => 'Time'},
                PrintConv => '$self->ConvertDateTime($val)',
                PrintConvInv => '$self->InverseDateTime($val,undef,1)',
            },
        },
    },
    # remove "MP" from tag name (was added only to avoid conflict with XMP-mwg-rs:RegionInfo)
    RegionInfoRegions                  => { Flat => 1, Name => 'RegionInfoRegions' },
    RegionInfoDateRegionsValid         => { Flat => 1, Name => 'RegionInfoDateRegionsValid' },
    # shorten flattened Regions tag names to make them easier to use
    RegionInfoRegionsRectangle         => { Flat => 1, Name => 'RegionRectangle' },
    RegionInfoRegionsPersonDisplayName => { Flat => 1, Name => 'RegionPersonDisplayName' },
    RegionInfoRegionsPersonEmailDigest => { Flat => 1, Name => 'RegionPersonEmailDigest' },
    RegionInfoRegionsPersonLiveIdCID   => { Flat => 1, Name => 'RegionPersonLiveIdCID' },
    RegionInfoRegionsPersonSourceID    => { Flat => 1, Name => 'RegionPersonSourceID' },
);

# Xtra tags written in MP4 files written by Microsoft Windows Media Player
# (ref http://msdn.microsoft.com/en-us/library/windows/desktop/dd562330(v=VS.85).aspx)
# Note: These tags are closely related to tags in Image::ExifTool::ASF::ExtendedDescr
#       and Image::ExifTool::WTV::Metadata
%Image::ExifTool::Microsoft::Xtra = (
    PROCESS_PROC => \&ProcessXtra,
    GROUPS => { 0 => 'QuickTime', 2 => 'Video' },
    VARS => { NO_ID => 1 },
    NOTES => q{
        Tags extracted from the Microsoft "Xtra" atom of QuickTime videos.  Tag ID's
        are not shown because some are unruly GUID's.
    },
    Abstract                    => { },
    AcquisitionTime             => { Groups => { 2 => 'Time' } },
    AcquisitionTimeDay          => { Groups => { 2 => 'Time' } },
    AcquisitionTimeMonth        => { Groups => { 2 => 'Time' } },
    AcquisitionTimeYear         => { Groups => { 2 => 'Time' } },
    AcquisitionTimeYearMonth    => { Groups => { 2 => 'Time' } },
    AcquisitionTimeYearMonthDay => { Groups => { 2 => 'Time' } },
    AlbumArtistSortOrder        => { },
    AlbumID                     => { },
    AlbumIDAlbumArtist          => { },
    AlbumTitleSortOrder         => { },
    AlternateSourceURL          => { },
    AudioBitrate                => { },
    AudioFormat                 => { },
    Author                      => { Groups => { 2 => 'Author' } },
    AuthorSortOrder             => { },
    AverageLevel                => { },
    Bitrate                     => { },
    BuyNow                      => { },
    BuyTickets                  => { },
    CallLetters                 => { },
    CameraManufacturer          => { },
    CameraModel                 => { },
    CDTrackEnabled              => { },
    Channels                    => { },
    chapterNum                  => { },
    Comment                     => { },
    ContentDistributorDuration  => { },
    Copyright                   => { Groups => { 2 => 'Author' } },
    Count                       => { },
    CurrentBitrate              => { },
    Description                 => { },
    DisplayArtist               => { },
    DLNAServerUDN               => { },
    DLNASourceURI               => { },
    DRMKeyID                    => { },
    DRMIndividualizedVersion    => { },
    DTCPIPHost                  => { },
    DTCPIPPort                  => { },
    Duration                    => { },
    DVDID                       => { },
    Event                       => { },
    FileSize                    => { },
    FileType                    => { },
    FourCC                      => { },
    FormatTag                   => { },
    FrameRate                   => { },
    Frequency                   => { },
    IsNetworkFeed               => { },
    Is_Protected                => 'IsProtected',
    IsVBR                       => { },
    LeadPerformer               => { },
    LibraryID                   => { },
    LibraryName                 => { },
    Location                    => { },
    MediaContentTypes           => { },
    MediaType                   => { },
    ModifiedBy                  => { },
    MoreInfo                    => { },
    PartOfSet                   => { },
    PeakValue                   => { },
    PixelAspectRatioX           => { },
    PixelAspectRatioY           => { },
    PlaylistIndex               => { },
    Provider                    => { },
    ProviderLogoURL             => { },
    ProviderURL                 => { },
    RadioBand                   => { },
    RadioFormat                 => { },
    RatingOrg                   => { },
    RecordingTime               => { Groups => { 2 => 'Time' } },
    RecordingTimeDay            => { Groups => { 2 => 'Time' } },
    RecordingTimeMonth          => { Groups => { 2 => 'Time' } },
    RecordingTimeYear           => { Groups => { 2 => 'Time' } },
    RecordingTimeYearMonth      => { Groups => { 2 => 'Time' } },
    RecordingTimeYearMonthDay   => { Groups => { 2 => 'Time' } },
    ReleaseDate                 => { Groups => { 2 => 'Time' } },
    ReleaseDateDay              => { Groups => { 2 => 'Time' } },
    ReleaseDateMonth            => { Groups => { 2 => 'Time' } },
    ReleaseDateYear             => { Groups => { 2 => 'Time' } },
    ReleaseDateYearMonth        => { Groups => { 2 => 'Time' } },
    ReleaseDateYearMonthDay     => { Groups => { 2 => 'Time' } },
    RequestState                => { },
    ShadowFilePath              => { },
    SourceURL                   => { },
    Subject                     => { },
    SyncState                   => { },
    Sync01                      => { },
    Sync02                      => { },
    Sync03                      => { },
    Sync04                      => { },
    Sync05                      => { },
    Sync06                      => { },
    Sync07                      => { },
    Sync08                      => { },
    Sync09                      => { },
    Sync10                      => { },
    Sync11                      => { },
    Sync12                      => { },
    Sync13                      => { },
    Sync14                      => { },
    Sync15                      => { },
    Sync16                      => { },
    SyncOnly                    => { },
    Temporary                   => { },
    Title                       => { },
    titleNum                    => { },
    TitleSortOrder              => { },
    TotalDuration               => { },
    TrackingID                  => { },
    UserCustom1                 => { },
    UserCustom2                 => { },
    UserEffectiveRating         => { },
    UserLastPlayedTime          => { },
    UserPlayCount               => { },
    UserPlaycountAfternoon      => { },
    UserPlaycountEvening        => { },
    UserPlaycountMorning        => { },
    UserPlaycountNight          => { },
    UserPlaycountWeekday        => { },
    UserPlaycountWeekend        => { },
    UserRating                  => { },
    UserServiceRating           => { },
    VideoBitrate                => { },
    VideoFormat                 => { },
    'WM/AlbumArtist'            => 'AlbumArtist',
    'WM/AlbumCoverURL'          => 'AlbumCoverURL',
    'WM/AlbumTitle'             => 'AlbumTitle',
    'WM/BeatsPerMinute'         => 'BeatsPerMinute',
    'WM/Category'               => 'Category',
    'WM/Composer'               => 'Composer',
    'WM/Conductor'              => 'Conductor',
    'WM/ContentDistributor'     => 'ContentDistributor',
    'WM/ContentDistributorType' => 'ContentDistributorType',
    'WM/ContentGroupDescription'=> 'ContentGroupDescription',
    'WM/Director'               => 'Director',
    'WM/EncodingTime'           => {
        Name => 'EncodingTime',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    'WM/Genre'                  => 'Genre',
    'WM/GenreID'                => 'GenreID',
    'WM/InitialKey'             => 'InitialKey',
    'WM/Language'               => 'Language',
    'WM/Lyrics'                 => 'Lyrics',
    'WM/MCDI'                   => 'MCDI',
    'WM/MediaClassPrimaryID'    => {
        Name => 'MediaClassPrimaryID',
        PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx
            'D1607DBC-E323-4BE2-86A1-48A42A28441E' => 'Music',
            'DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B' => 'Video',
            '01CD0F29-DA4E-4157-897B-6275D50C4F11' => 'Audio (not music)',
            'FCF24A76-9A57-4036-990D-E35DD8B244E1' => 'Other (not audio or video)',
        },
    },
    'WM/MediaClassSecondaryID' => {
        Name => 'MediaClassSecondaryID',
        PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx
            'E0236BEB-C281-4EDE-A36D-7AF76A3D45B5' => 'Audio Book',
            '3A172A13-2BD9-4831-835B-114F6A95943F' => 'Spoken Word',
            '6677DB9B-E5A0-4063-A1AD-ACEB52840CF1' => 'Audio News',
            '1B824A67-3F80-4E3E-9CDE-F7361B0F5F1B' => 'Talk Show',
            '1FE2E091-4E1E-40CE-B22D-348C732E0B10' => 'Video News',
            'D6DE1D88-C77C-4593-BFBC-9C61E8C373E3' => 'Web-based Video',
            '00033368-5009-4AC3-A820-5D2D09A4E7C1' => 'Sound Clip from Game',
            'F24FF731-96FC-4D0F-A2F5-5A3483682B1A' => 'Song from Game',
            'E3E689E2-BA8C-4330-96DF-A0EEEFFA6876' => 'Music Video',
            'B76628F4-300D-443D-9CB5-01C285109DAF' => 'Home Movie',
            'A9B87FC9-BD47-4BF0-AC4F-655B89F7D868' => 'Feature Film',
            'BA7F258A-62F7-47A9-B21F-4651C42A000E' => 'TV Show',
            '44051B5B-B103-4B5C-92AB-93060A9463F0' => 'Corporate Video',
            '0B710218-8C0C-475E-AF73-4C41C0C8F8CE' => 'Home Video from Pictures',
            '00000000-0000-0000-0000-000000000000' => 'Unknown Content', #PH
        },
    },
    'WM/MediaOriginalBroadcastDateTime' => {
        Name => 'MediaOriginalBroadcastDateTime',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    'WM/MediaOriginalChannel'   => 'MediaOriginalChannel',
    'WM/MediaStationName'       => 'MediaStationName',
    'WM/Mood'                   => 'Mood',
    'WM/OriginalAlbumTitle'     => 'OriginalAlbumTitle',
    'WM/OriginalArtist'         => 'OriginalArtist',
    'WM/OriginalLyricist'       => 'OriginalLyricist',
    'WM/ParentalRating'         => 'ParentalRating',
    'WM/PartOfSet'              => 'PartOfSet',
    'WM/Period'                 => 'Period',
    'WM/Producer'               => 'Producer',
    'WM/ProtectionType'         => 'ProtectionType',
    'WM/Provider'               => 'Provider',
    'WM/ProviderRating'         => 'ProviderRating',
    'WM/ProviderStyle'          => 'ProviderStyle',
    'WM/Publisher'              => 'Publisher',
    'WM/SharedUserRating'       => 'SharedUserRating',
    'WM/SubscriptionContentID'  => 'SubscriptionContentID',
    'WM/SubTitle'               => 'Subtitle',
    'WM/SubTitleDescription'    => 'SubtitleDescription',
    'WM/TrackNumber'            => 'TrackNumber',
    'WM/UniqueFileIdentifier'   => 'UniqueFileIdentifier',
    'WM/VideoFrameRate'         => 'VideoFrameRate',
    'WM/VideoHeight'            => 'VideoHeight',
    'WM/VideoWidth'             => 'VideoWidth',
    'WM/WMCollectionGroupID'    => 'WMCollectionGroupID',
    'WM/WMCollectionID'         => 'WMCollectionID',
    'WM/WMContentID'            => 'WMContentID',
    'WM/WMShadowFileSourceDRMType' => 'WMShadowFileSourceDRMType',
    'WM/WMShadowFileSourceFileType' => 'WMShadowFileSourceFileType',
    'WM/Writer'                 => 'Writer',
    'WM/Year'                   => { Name => 'Year', Groups => { 2 => 'Time' } },

    # I can't find documentation for the following tags in videos,
    # but the tag ID's correspond to Microsoft property GUID+ID's
    # References:
    #  http://msdn.microsoft.com/en-us/library/cc251929%28v=prot.10%29.aspx
    #  http://multi-rename-script.googlecode.com/svn-history/r4/trunk/plugins/ShellDetails/ShellDetails.ini
    # I have observed only 1 so far:
    '{2CBAA8F5-D81F-47CA-B17A-F8D822300131} 100' => {
        Name => 'DateAcquired',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    # the following have not yet been observed...
    '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 10'    => 'Name',
    '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 12'    => 'Size',
    '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 4'     => 'Type',
    '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 14'    => {
        Name => 'DateModified',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 15'    => {
        Name => 'DateCreated',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 16'    => {
        Name => 'DateAccessed',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 13'    => 'Attributes',
    '{D8C3986F-813B-449C-845D-87B95D674ADE} 2'     => 'Status',
    '{9B174B34-40FF-11D2-A27E-00C04FC30871} 4'     => 'Owner',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 4'     => {
        Name => 'Author',
        Groups => { 2 => 'Author' },
    },
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 2'     => 'Title',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 3'     => 'Subject',
    '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 2'     => 'Category',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 14'    => 'Pages',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 6'     => 'Comments',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 11'    => {
        Name => 'Copyright',
        Groups => { 2 => 'Author' },
    },
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 2'     => 'Artist',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 4'     => 'AlbumTitle',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 5'     => {
        Name => 'Year',
        Groups => { 2 => 'Time' },
    },
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 7'     => 'TrackNumber',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 11'    => 'Genre',
    '{64440490-4C8B-11D1-8B70-080036B11A03} 3'     => 'Duration',
    '{64440490-4C8B-11D1-8B70-080036B11A03} 4'     => 'Bitrate',
    '{AEAC19E4-89AE-4508-B9B7-BB867ABEE2ED} 2'     => 'Protected',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 272'   => 'CameraModel',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 36867' => {
        Name => 'DatePictureTaken',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{6444048F-4C8B-11D1-8B70-080036B11A03} 13'    => 'Dimensions',
    '{6444048F-4C8B-11D1-8B70-080036B11A03} 3'     => 'Untitled0',
    '{6444048F-4C8B-11D1-8B70-080036B11A03} 4'     => 'Untitled1',
    '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 2'     => 'EpisodeName',
    '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 3'     => 'ProgramDescription',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 12'    => 'Untitled2',
    '{64440490-4C8B-11D1-8B70-080036B11A03} 6'     => 'AudioSampleSize',
    '{64440490-4C8B-11D1-8B70-080036B11A03} 5'     => 'AudioSampleRate',
    '{64440490-4C8B-11D1-8B70-080036B11A03} 7'     => 'Channels',
    '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 15'    => 'Company',
    '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 3'     => 'Description',
    '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 4'     => 'FileVersion',
    '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 7'     => 'ProductName',
    '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 8'     => 'ProductVersion',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 5'     => 'Keywords',
    '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 11'    => 'Type',
    '{6D24888F-4718-4BDA-AFED-EA0FB4386CD8} 100'   => 'OfflineStatus',
    '{A94688B6-7D9F-4570-A648-E3DFC0AB2B3F} 100'   => 'OfflineAvailability',
    '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 9'     => 'PerceivedType',
    '{1E3EE840-BC2B-476C-8237-2ACD1A839B22} 3'     => 'Kinds',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 36'    => 'Conductors',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 9'     => 'Rating',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 271'   => 'CameraMaker',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 18'    => 'ProgramName',
    '{293CA35A-09AA-4DD2-B180-1FE245728A52} 100'   => 'Duration',
    '{BFEE9149-E3E2-49A7-A862-C05988145CEC} 100'   => 'IsOnline',
    '{315B9C8D-80A9-4EF9-AE16-8E746DA51D70} 100'   => 'IsRecurring',
    '{F6272D18-CECC-40B1-B26A-3911717AA7BD} 100'   => 'Location',
    '{D55BAE5A-3892-417A-A649-C6AC5AAAEAB3} 100'   => 'OptionalAttendeeAddresses',
    '{09429607-582D-437F-84C3-DE93A2B24C3C} 100'   => 'OptionalAttendees',
    '{744C8242-4DF5-456C-AB9E-014EFB9021E3} 100'   => 'OrganizerAddress',
    '{AAA660F9-9865-458E-B484-01BC7FE3973E} 100'   => 'OrganizerName',
    '{72FC5BA4-24F9-4011-9F3F-ADD27AFAD818} 100'   => 'ReminderTime',
    '{0BA7D6C3-568D-4159-AB91-781A91FB71E5} 100'   => 'RequiredAttendeeAddresses',
    '{B33AF30B-F552-4584-936C-CB93E5CDA29F} 100'   => 'RequiredAttendees',
    '{00F58A38-C54B-4C40-8696-97235980EAE1} 100'   => 'Resources',
    '{5BF396D4-5EB2-466F-BDE9-2FB3F2361D6E} 100'   => 'Free-busyStatus',
    '{9B174B35-40FF-11D2-A27E-00C04FC30871} 3'     => 'TotalSize',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 9'     => 'AccountName',
    '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 5'     => 'Computer',
    '{9AD5BADB-CEA7-4470-A03D-B84E51B9949E} 100'   => 'Anniversary',
    '{CD102C9C-5540-4A88-A6F6-64E4981C8CD1} 100'   => 'AssistantsName',
    '{9A93244D-A7AD-4FF8-9B99-45EE4CC09AF6} 100'   => 'AssistantsPhone',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 47'    => 'Birthday',
    '{730FB6DD-CF7C-426B-A03F-BD166CC9EE24} 100'   => 'BusinessAddress',
    '{402B5934-EC5A-48C3-93E6-85E86A2D934E} 100'   => 'BusinessCity',
    '{B0B87314-FCF6-4FEB-8DFF-A50DA6AF561C} 100'   => 'BusinessCountry-Region',
    '{BC4E71CE-17F9-48D5-BEE9-021DF0EA5409} 100'   => 'BusinessPOBox',
    '{E1D4A09E-D758-4CD1-B6EC-34A8B5A73F80} 100'   => 'BusinessPostalCode',
    '{446F787F-10C4-41CB-A6C4-4D0343551597} 100'   => 'BusinessStateOrProvince',
    '{DDD1460F-C0BF-4553-8CE4-10433C908FB0} 100'   => 'BusinessStreet',
    '{91EFF6F3-2E27-42CA-933E-7C999FBE310B} 100'   => 'BusinessFax',
    '{56310920-2491-4919-99CE-EADB06FAFDB2} 100'   => 'BusinessHomePage',
    '{6A15E5A0-0A1E-4CD7-BB8C-D2F1B0C929BC} 100'   => 'BusinessPhone',
    '{BF53D1C3-49E0-4F7F-8567-5A821D8AC542} 100'   => 'CallbackNumber',
    '{8FDC6DEA-B929-412B-BA90-397A257465FE} 100'   => 'CarPhone',
    '{D4729704-8EF1-43EF-9024-2BD381187FD5} 100'   => 'Children',
    '{8589E481-6040-473D-B171-7FA89C2708ED} 100'   => 'CompanyMainPhone',
    '{FC9F7306-FF8F-4D49-9FB6-3FFE5C0951EC} 100'   => 'Department',
    '{F8FA7FA3-D12B-4785-8A4E-691A94F7A3E7} 100'   => 'E-mailAddress',
    '{38965063-EDC8-4268-8491-B7723172CF29} 100'   => 'E-mail2',
    '{644D37B4-E1B3-4BAD-B099-7E7C04966ACA} 100'   => 'E-mail3',
    '{84D8F337-981D-44B3-9615-C7596DBA17E3} 100'   => 'E-mailList',
    '{CC6F4F24-6083-4BD4-8754-674D0DE87AB8} 100'   => 'E-mailDisplayName',
    '{F1A24AA7-9CA7-40F6-89EC-97DEF9FFE8DB} 100'   => 'FileAs',
    '{14977844-6B49-4AAD-A714-A4513BF60460} 100'   => 'FirstName',
    '{635E9051-50A5-4BA2-B9DB-4ED056C77296} 100'   => 'FullName',
    '{3C8CEE58-D4F0-4CF9-B756-4E5D24447BCD} 100'   => 'Gender',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 70'    => 'GivenName',
    '{5DC2253F-5E11-4ADF-9CFE-910DD01E3E70} 100'   => 'Hobbies',
    '{98F98354-617A-46B8-8560-5B1B64BF1F89} 100'   => 'HomeAddress',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 65'    => 'HomeCity',
    '{08A65AA1-F4C9-43DD-9DDF-A33D8E7EAD85} 100'   => 'HomeCountry-Region',
    '{7B9F6399-0A3F-4B12-89BD-4ADC51C918AF} 100'   => 'HomePOBox',
    '{8AFCC170-8A46-4B53-9EEE-90BAE7151E62} 100'   => 'HomePostalCode',
    '{C89A23D0-7D6D-4EB8-87D4-776A82D493E5} 100'   => 'HomeStateOrProvince',
    '{0ADEF160-DB3F-4308-9A21-06237B16FA2A} 100'   => 'HomeStreet',
    '{660E04D6-81AB-4977-A09F-82313113AB26} 100'   => 'HomeFax',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 20'    => 'HomePhone',
    '{D68DBD8A-3374-4B81-9972-3EC30682DB3D} 100'   => 'IMAddresses',
    '{F3D8F40D-50CB-44A2-9718-40CB9119495D} 100'   => 'Initials',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 6'     => 'JobTitle',
    '{97B0AD89-DF49-49CC-834E-660974FD755B} 100'   => 'Label',
    '{8F367200-C270-457C-B1D4-E07C5BCD90C7} 100'   => 'LastName',
    '{C0AC206A-827E-4650-95AE-77E2BB74FCC9} 100'   => 'MailingAddress',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 71'    => 'MiddleName',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 35'    => 'CellPhone',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 74'    => 'Nickname',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 7'     => 'OfficeLocation',
    '{508161FA-313B-43D5-83A1-C1ACCF68622C} 100'   => 'OtherAddress',
    '{6E682923-7F7B-4F0C-A337-CFCA296687BF} 100'   => 'OtherCity',
    '{8F167568-0AAE-4322-8ED9-6055B7B0E398} 100'   => 'OtherCountry-Region',
    '{8B26EA41-058F-43F6-AECC-4035681CE977} 100'   => 'OtherPOBox',
    '{95C656C1-2ABF-4148-9ED3-9EC602E3B7CD} 100'   => 'OtherPostalCode',
    '{71B377D6-E570-425F-A170-809FAE73E54E} 100'   => 'OtherStateOrProvince',
    '{FF962609-B7D6-4999-862D-95180D529AEA} 100'   => 'OtherStreet',
    '{D6304E01-F8F5-4F45-8B15-D024A6296789} 100'   => 'Pager',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 69'    => 'PersonalTitle',
    '{C8EA94F0-A9E3-4969-A94B-9C62A95324E0} 100'   => 'City',
    '{E53D799D-0F3F-466E-B2FF-74634A3CB7A4} 100'   => 'Country-Region',
    '{DE5EF3C7-46E1-484E-9999-62C5308394C1} 100'   => 'POBox',
    '{18BBD425-ECFD-46EF-B612-7B4A6034EDA0} 100'   => 'PostalCode',
    '{F1176DFE-7138-4640-8B4C-AE375DC70A6D} 100'   => 'StateOrProvince',
    '{63C25B20-96BE-488F-8788-C09C407AD812} 100'   => 'Street',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 48'    => 'PrimaryE-mail',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 25'    => 'PrimaryPhone',
    '{7268AF55-1CE4-4F6E-A41F-B6E4EF10E4A9} 100'   => 'Profession',
    '{9D2408B6-3167-422B-82B0-F583B7A7CFE3} 100'   => 'Spouse',
    '{176DC63C-2688-4E89-8143-A347800F25E9} 73'    => 'Suffix',
    '{AAF16BAC-2B55-45E6-9F6D-415EB94910DF} 100'   => 'TTY-TTDPhone',
    '{C554493C-C1F7-40C1-A76C-EF8C0614003E} 100'   => 'Telex',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 18'    => 'Webpage',
    '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 27'    => 'Status',
    '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 26'    => 'ContentType',
    '{43F8D7B7-A444-4F87-9383-52271C9B915C} 100'   => {
        Name => 'DateArchived',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{72FAB781-ACDA-43E5-B155-B2434F85E678} 100'   => {
        Name => 'DateCompleted',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 18258' => {
        Name => 'DateImported',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{276D7BB0-5B34-4FB0-AA4B-158ED12A1809} 100'   => 'ClientID',
    '{F334115E-DA1B-4509-9B3D-119504DC7ABB} 100'   => 'Contributors',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 11'    => 'LastPrinted',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 13'    => {
        Name => 'DateLastSaved',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{1E005EE6-BF27-428B-B01C-79676ACD2870} 100'   => 'Division',
    '{E08805C8-E395-40DF-80D2-54F0D6C43154} 100'   => 'DocumentID',
    '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 7'     => 'Slides',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 10'    => 'TotalEditingTime',
    '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 15'    => 'WordCount',
    '{3F8472B5-E0AF-4DB2-8071-C53FE76AE7CE} 100'   => 'DueDate',
    '{C75FAA05-96FD-49E7-9CB4-9F601082D553} 100'   => 'EndDate',
    '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 12'    => 'FileCount',
    '{41CF5AE0-F75A-4806-BD87-59C7D9248EB9} 100'   => 'WindowsFileName',
    '{67DF94DE-0CA7-4D6F-B792-053A3E4F03CF} 100'   => 'FlagColor',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 12'    => 'FlagStatus',
    '{9B174B35-40FF-11D2-A27E-00C04FC30871} 2'     => 'SpaceFree',
    '{6444048F-4C8B-11D1-8B70-080036B11A03} 7'     => 'BitDepth',
    '{6444048F-4C8B-11D1-8B70-080036B11A03} 5'     => 'HorizontalResolution',
    '{6444048F-4C8B-11D1-8B70-080036B11A03} 6'     => 'VerticalResolution',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 11'    => 'Importance',
    '{F23F425C-71A1-4FA8-922F-678EA4A60408} 100'   => 'IsAttachment',
    '{5CDA5FC8-33EE-4FF3-9094-AE7BD8868C4D} 100'   => 'IsDeleted',
    '{5DA84765-E3FF-4278-86B0-A27967FBDD03} 100'   => 'HasFlag',
    '{A6F360D2-55F9-48DE-B909-620E090A647C} 100'   => 'IsCompleted',
    '{346C8BD1-2E6A-4C45-89A4-61B78E8E700F} 100'   => 'Incomplete',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 10'    => 'ReadStatus',
    '{EF884C5B-2BFE-41BB-AAE5-76EEDF4F9902} 100'   => 'Shared',
    '{D0A04F0A-462A-48A4-BB2F-3706E88DBD7D} 100'   => {
        Name => 'Creator',
        Groups => { 2 => 'Author' },
    },
    '{F7DB74B4-4287-4103-AFBA-F1B13DCD75CF} 100'   => {
        Name => 'Date',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 2'     => 'FolderName',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 6'     => 'FolderPath',
    '{DABD30ED-0043-4789-A7F8-D013A4736622} 100'   => 'Folder',
    '{D4D0AA16-9948-41A4-AA85-D97FF9646993} 100'   => 'Participants',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 7'     => 'Path',
    '{DEA7C82C-1D89-4A66-9427-A4E3DEBABCB1} 100'   => 'ContactNames',
    '{95BEB1FC-326D-4644-B396-CD3ED90E6DDF} 100'   => 'EntryType',
    '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 28'    => 'Language',
    '{5CBF2787-48CF-4208-B90E-EE5E5D420294} 23'    => {
        Name => 'DateVisited',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{5CBF2787-48CF-4208-B90E-EE5E5D420294} 21'    => 'Description',
    '{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25} 3'     => 'LinkStatus',
    '{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25} 2'     => 'LinkTarget',
    '{5CBF2787-48CF-4208-B90E-EE5E5D420294} 2'     => 'URL',
    '{2E4B640D-5019-46D8-8881-55414CC5CAA0} 100'   => 'MediaCreated',
    '{DE41CC29-6971-4290-B472-F59F2E2F31E2} 100'   => {
        Name => 'DateReleased',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{64440492-4C8B-11D1-8B70-080036B11A03} 36'    => 'EncodedBy',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 22'    => 'Producers',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 30'    => 'Publisher',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 38'    => 'Subtitle',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 34'    => 'UserWebURL',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 23'    => 'Writers',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 21'    => 'Attachments',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 2'     => 'BccAddresses',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 3'     => 'BccNames',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 4'     => 'CcAddresses',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 5'     => 'CcNames',
    '{DC8F80BD-AF1E-4289-85B6-3DFC1B493992} 100'   => 'ConversationID',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 20'    => {
        Name => 'DateReceived',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 19'    => {
        Name => 'DateSent',
        Groups => { 2 => 'Time' },
        PrintConv => '$self->ConvertDateTime($val)',
    },
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 13'    => 'FromAddresses',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 14'    => 'FromNames',
    '{9C1FCF74-2D97-41BA-B4AE-CB2E3661A6E4} 8'     => 'HasAttachments',
    '{0BE1C8E7-1981-4676-AE14-FDD78F05A6E7} 100'   => 'SenderAddress',
    '{0DA41CFA-D224-4A18-AE2F-596158DB4B3A} 100'   => 'SenderName',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 15'    => 'Store',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 16'    => 'ToAddresses',
    '{BCCC8A3C-8CEF-42E5-9B1C-C69079398BC7} 100'   => 'ToDoTitle',
    '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 17'    => 'ToNames',
    '{FDF84370-031A-4ADD-9E91-0D775F1C6605} 100'   => 'Mileage',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 13'    => 'AlbumArtist',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 35'    => 'Beats-per-minute',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 19'    => 'Composers',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 34'    => 'InitialKey',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 39'    => 'Mood',
    '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 37'    => 'PartOfSet',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 31'    => 'Period',
    '{4776CAFA-BCE4-4CB1-A23E-265E76D8EB11} 100'   => 'Color',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 21'    => 'ParentalRating',
    '{10984E0A-F9F2-4321-B7EF-BAF195AF4319} 100'   => 'ParentalRatingReason',
    '{9B174B35-40FF-11D2-A27E-00C04FC30871} 5'     => 'SpaceUsed',
    '{D35F743A-EB2E-47F2-A286-844132CB1427} 100'   => 'ExifVersion',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 18248' => 'Event',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37380' => 'ExposureBias',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 34850' => 'ExposureProgram',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 33434' => 'ExposureTime',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 33437' => 'F-stop',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37385' => 'FlashMode',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37386' => 'FocalLength',
    '{A0E74609-B84D-4F49-B860-462BD9971F98} 100'   => 'FocalLength35mm',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 34855' => 'ISOSpeed',
    '{E6DDCAF7-29C5-4F0A-9A68-D19412EC7090} 100'   => 'LensMaker',
    '{E1277516-2B5F-4869-89B1-2E585BD38B7A} 100'   => 'LensModel',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37384' => 'LightSource',
    '{08F6D7C2-E3F2-44FC-AF1E-5AA5C81A2D3E} 100'   => 'MaxAperture',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37383' => 'MeteringMode',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 274'   => 'Orientation',
    '{6D217F6D-3F6A-4825-B470-5F03CA2FBE9B} 100'   => 'ProgramMode',
    '{49237325-A95A-4F67-B211-816B2D45D2E0} 100'   => 'Saturation',
    '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37382' => 'SubjectDistance',
    '{EE3D3D8A-5381-4CFA-B13B-AAF66B5F4EC9} 100'   => 'WhiteBalance',
    '{9C1FCF74-2D97-41BA-B4AE-CB2E3661A6E4} 5'     => 'Priority',
    '{39A7F922-477C-48DE-8BC8-B28441E342E3} 100'   => 'Project',
    '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 7'     => 'ChannelNumber',
    '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 12'    => 'ClosedCaptioning',
    '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 13'    => 'Rerun',
    '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 14'    => 'SAP',
    '{4684FE97-8765-4842-9C13-F006447B178C} 100'   => 'BroadcastDate',
    '{A5477F61-7A82-4ECA-9DDE-98B69B2479B3} 100'   => 'RecordingTime',
    '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 5'     => 'StationCallSign',
    '{1B5439E7-EBA1-4AF8-BDD7-7AF1D4549493} 100'   => 'StationName',
    '{560C36C0-503A-11CF-BAA1-00004C752A9A} 2'     => 'AutoSummary',
    '{560C36C0-503A-11CF-BAA1-00004C752A9A} 3'     => 'Summary',
    '{49691C90-7E17-101A-A91C-08002B2ECDA9} 3'     => 'SearchRanking',
    '{F8D3F6AC-4874-42CB-BE59-AB454B30716A} 100'   => 'Sensitivity',
    '{EF884C5B-2BFE-41BB-AAE5-76EEDF4F9902} 200'   => 'SharedWith',
    '{668CDFA5-7A1B-4323-AE4B-E527393A1D81} 100'   => 'Source',
    '{48FD6EC8-8A12-4CDF-A03E-4EC5A511EDDE} 100'   => 'StartDate',
    '{D37D52C6-261C-4303-82B3-08B926AC6F12} 100'   => 'BillingInformation',
    '{084D8A0A-E6D5-40DE-BF1F-C8820E7C877C} 100'   => 'Complete',
    '{08C7CC5F-60F2-4494-AD75-55E3E0B5ADD0} 100'   => 'TaskOwner',
    '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 14'    => 'TotalFileSize',
    '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 9'     => 'LegalTrademarks',
    '{64440491-4C8B-11D1-8B70-080036B11A03} 10'    => 'VideoCompression',
    '{64440492-4C8B-11D1-8B70-080036B11A03} 20'    => 'Directors',
    '{64440491-4C8B-11D1-8B70-080036B11A03} 8'     => 'DataRate',
    '{64440491-4C8B-11D1-8B70-080036B11A03} 4'     => 'FrameHeight',
    '{64440491-4C8B-11D1-8B70-080036B11A03} 6'     => 'FrameRate',
    '{64440491-4C8B-11D1-8B70-080036B11A03} 3'     => 'FrameWidth',
    '{64440491-4C8B-11D1-8B70-080036B11A03} 43'    => 'TotalBitrate',
);

#------------------------------------------------------------------------------
# Extract information from Xtra MP4 atom
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
# Returns: 1 on success
# Reference: http://code.google.com/p/mp4v2/ [since removed from trunk]
sub ProcessXtra($$$)
{
    my ($et, $dirInfo, $tagTablePtr) = @_;
    my $dataPt = $$dirInfo{DataPt};
    my $dataPos = $$dirInfo{Base} || 0;
    my $dataLen = $$dirInfo{DataLen};
    my $pos = 0;
    $et->VerboseDir('Xtra', 0, $dataLen);
    for (;;) {
        last if $pos + 4 > $dataLen;
        my $size = Get32u($dataPt, $pos); # (includes $size word)
        last if $size < 8 or $pos + $size > $dataLen;
        my $tagLen = Get32u($dataPt, $pos + 4);
        last if $tagLen + 18 > $size;
        my $tag = substr($$dataPt, $pos + 8, $tagLen);
        # (version flags according to the reference, but looks more like a count - PH)
        my $count = Get32u($dataPt, $pos + $tagLen + 8);
        my ($i, $valPos, $valLen, $valType, $val, $format, @vals);
        # point to start of first value (after 4-byte length and 2-byte type)
        $valPos = $pos + $tagLen + 18;
        for ($i=0; ;) {
            # (stored value includes size of $valLen and $valType, so subtract 6)
            $valLen  = Get32u($dataPt, $valPos - 6) - 6;
            my $more = $pos + $size - $valPos - $valLen;
            last if $more < 0;
            $valType = Get16u($dataPt, $valPos - 2);
            $val = substr($$dataPt, $valPos, $valLen);
            # Note: all dumb Microsoft values are little-endian inside a big-endian-format file
            SetByteOrder('II');
            if ($valType == 8) {
                $format = 'Unicode';
                $val = $et->Decode($val, 'UCS2');
            } elsif ($valType == 19 and $valLen == 8) {
                $format = 'int64u';
                $val = Get64u(\$val, 0);
            } elsif ($valType == 21 and $valLen == 8) {
                $format = 'date';
                $val = Get64u(\$val, 0);
                # convert time from 100 ns intervals since Jan 1, 1601
                $val = $val * 1e-7 - 11644473600 if $val;
                # (the Nikon S100 uses UTC timezone, same as ASF - PH)
                $val = Image::ExifTool::ConvertUnixTime($val) . 'Z';
            } elsif ($valType == 72 and $valLen == 16) {
                $format = 'GUID';
                $val = uc unpack('H*',pack('NnnNN',unpack('VvvNN',$val)));
                $val =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/;
            } elsif ($valType == 65 && $valLen > 4) { #PH (empirical)
                $format = 'variant';
                require Image::ExifTool::FlashPix;
                my $vPos = $valPos; # (necessary because ReadFPXValue updates this)
                # read entry as a VT_VARIANT (use FlashPix module for this)
                $val = Image::ExifTool::FlashPix::ReadFPXValue($et, $dataPt, $vPos,
                       Image::ExifTool::FlashPix::VT_VARIANT(), $valPos+$valLen, 1);
            } else {
                $format = "Unknown($valType)";
            }
            SetByteOrder('MM'); # back to native QuickTime byte ordering
            last if ++$i >= $count or $more < 6;
            push @vals, $val;
            undef $val;
            $valPos += $valLen + 6; # step to next value
        }
        if (@vals) {
            push @vals, $val if defined $val;
            $val = \@vals;
            $valPos = $pos + $tagLen + 18;
            $valLen = $size - 18 - $tagLen;
        }
        if ($tagLen > 0 and $valLen > 0) {
            my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
            unless ($tagInfo) {
                # generate tag information for unrecognized tags
                my $name = $tag;
                $name =~ s{^WM/}{};
              # $name =~ tr/-_A-Za-z0-9//dc;
                if ($name =~ /^[-\w]+$/) {
                    $tagInfo = { Name => ucfirst($name) };
                    AddTagToTable($tagTablePtr, $tag, $tagInfo);
                    $et->VPrint(0, $$et{INDENT}, "[adding Microsoft:$tag]\n");
                }
            }
            $et->HandleTag($tagTablePtr, $tag, $val,
                TagInfo => $tagInfo,
                DataPt  => $dataPt,
                DataPos => $dataPos,
                Start   => $valPos,
                Size    => $valLen,
                Format  => $format,
                Extra   => " count=$count type=$valType",
            );
        }
        $pos += $size;  # step to next entry
    }
    return 1;
}

1;  # end

__END__

=head1 NAME

Image::ExifTool::Microsoft - Definitions for custom Microsoft tags

=head1 SYNOPSIS

This module is used by Image::ExifTool

=head1 DESCRIPTION

This module contains definitions required by Image::ExifTool to interpret
Microsoft-specific EXIF and XMP tags.

=head1 AUTHOR

Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)

This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=head1 REFERENCES

=over 4

=item L<http://research.microsoft.com/en-us/um/redmond/groups/ivm/hdview/hdmetadataspec.htm>

=back

=head1 SEE ALSO

L<Image::ExifTool::TagNames/Microsoft Tags>,
L<Image::ExifTool(3pm)|Image::ExifTool>

=cut

