Blog. Just Blog

Универсальное извлечение метаданных из файлов

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Универсальное извлечение метаданных из файлов
Универсальное извлечение метаданных из файлов

За последнее время на сайте появилось немало статей, посвященных работе с метаданными файлов различных форматов. Но там рассматривались только определенные форматы и использовались методы, заточенные под определенную структуру файлов. Но в Windows есть очень мощные инструменты, которые позволяют получить множество полезной информации практически из любого файла, независимо от его структуры и типа.

Начинаем, как обычно, с описания задействованных структур, интерфейсов и констант. Даже интересно, когда-нибудь в "коробочном" FASM появится поддержка структур и констант хотя бы до уровня WinXP SP3?
  1. ; GUID {886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}
  2. IID_IPropertyStore \
  3.     dd 0886D8EEBh
  4.     dw 08CF2h
  5.     dw 04446h
  6.     db 08Dh, 002h, 0CDh, 0BAh, 01Dh, 0BDh, 0CFh, 099h
  7.  
  8. ; GUID {CA724E8A-C3E6-442B-88A4-6FB0DB8035A3}
  9. IID_IPropertySystem \
  10.     dd 0CA724E8Ah
  11.     dw 0C3E6h
  12.     dw 0442Bh
  13.     db 088h, 0A4h, 06Fh, 0B0h, 0DBh, 080h, 035h, 0A3h
  14.  
  15. ; IID_IPropertySystem Interface
  16. struct IPropertySystem
  17.     ; IUnknown
  18.     QueryInterface                       dd ?   ; 000h
  19.     AddRef                               dd ?   ; 004h
  20.     Release                              dd ?   ; 008h
  21.     ; IPropertySystem
  22.     GetPropertyDescription               dd ?   ; 00Ch
  23.     GetPropertyDescriptionByName         dd ?   ; 010h
  24.     GetPropertyDescriptionListFromString dd ?   ; 014h
  25.     EnumeratePropertyDescriptions        dd ?   ; 018h
  26.     FormatForDisplay                     dd ?   ; 01Ch
  27.     FormatForDisplayAlloc                dd ?   ; 020h
  28.     RegisterPropertySchema               dd ?   ; 024h
  29.     UnregisterPropertySchema             dd ?   ; 028h
  30.     RefreshPropertySchema                dd ?   ; 02Ch
  31. ends
  32.  
  33. ; GUID {1F9FC1D0-C39B-4B26-817F-011967D3440E}
  34. IID_IPropertyDescriptionList \
  35.     dd 01F9FC1D0h
  36.     dw 0C39Bh
  37.     dw 04B26h
  38.     db 081h, 07Fh, 001h, 019h, 067h, 0D3h, 044h, 00Eh
  39.  
  40. ; IID_IPropertyDescriptionList Interface
  41. struct IPropertyDescriptionList
  42.     ; IUnknown
  43.     QueryInterface dd ?   ; 000h
  44.     AddRef         dd ?   ; 004h
  45.     Release        dd ?   ; 008h
  46.     ; IPropertyDescriptionList
  47.     GetCount       dd ?   ; 00Ch
  48.     GetAt          dd ?   ; 010h
  49. ends
  50.  
  51. ; GUID {6F79D558-3E96-4549-A1D1-7D75D2288814}
  52. IID_IPropertyDescription \
  53.     dd 06F79D558h
  54.     dw 03E96h
  55.     dw 04549h
  56.     db 0A1h, 0D1h, 07Dh, 075h, 0D2h, 028h, 088h, 014h
  57.  
  58. ; IID_IPropertyDescription Interface
  59. struct IPropertyDescription
  60.     ; IUnknown
  61.     QueryInterface             dd ?   ; 000h
  62.     AddRef                     dd ?   ; 004h
  63.     Release                    dd ?   ; 008h
  64.     ; IPropertyDescription
  65.     GetPropertyKey             dd ?   ; 00Ch
  66.     GetCanonicalName           dd ?   ; 010h
  67.     GetPropertyType            dd ?   ; 014h
  68.     GetDisplayName             dd ?   ; 018h
  69.     GetEditInvitation          dd ?   ; 01Ch
  70.     GetTypeFlags               dd ?   ; 020h
  71.     GetViewFlags               dd ?   ; 024h
  72.     GetDefaultColumnWidth      dd ?   ; 028h
  73.     GetDisplayType             dd ?   ; 02Ch
  74.     GetColumnState             dd ?   ; 030h
  75.     GetGroupingRange           dd ?   ; 034h
  76.     GetRelativeDescriptionType dd ?   ; 038h
  77.     GetRelativeDescription     dd ?   ; 03Ch
  78.     GetSortDescription         dd ?   ; 040h
  79.     GetSortDescriptionLabel    dd ?   ; 044h
  80.     GetAggregationType         dd ?   ; 048h
  81.     GetConditionType           dd ?   ; 04Ch
  82.     GetEnumTypeList            dd ?   ; 050h
  83.     CoerceToCanonicalValue     dd ?   ; 054h
  84.     FormatForDisplay           dd ?   ; 058h
  85.     IsValueCanonical           dd ?   ; 05Ch
  86. ends
  87.  
  88. PDFF_DEFAULT  = 0
  89. PDEF_VIEWABLE = 3
  90. GPS_READWRITE = 2
Если быть точным, то это не совсем метаданные, это так называемые системные свойства. Но, например, для музыкальных и графических файлов большая часть информации из EXIF и музыкальных тегов проецируется в системные свойства, так что их тоже можно использовать.

Начнем с теории. Для получения доступа к системным свойствам используется функция PSGetPropertySystem, которая возвращает интерфейс IPropertySystem для работы с ними. Дальше получаем объект списка всех свойств IPropertyDescriptionList, их количество, а потом поочередно перебираем все свойства в этом списке. Для каждого свойства можно получить его каноническое имя, человекопонятное название и, соответственно, значение. Для конвертации значения свойства из системного представления в привычный для человека вид используется функция PSFormatPropertyValue. Получив объект свойств выбранного файла, можно поочередно запрашивать каждое из перечисляемых системных свойств. Если результат получен, то такое свойство у файла имеется, если нет, то нет. Таким образом можно получить все имеющиеся системные свойства, они же метаданные, для любого файла.
  1.         invoke  CoInitialize,0
  2.  
  3.         ; Получить полный путь к файлу
  4.         invoke  GetFullPathName,sample,MAX_PATH,fname,NULL
  5.  
  6.         ; Получить доступ к его свойствам
  7.         invoke  SHGetPropertyStoreFromParsingName,fname,\
  8.                 NULL,GPS_READWRITE,IID_IPropertyStore,pStore
  9.  
  10.         ; Получить объект для работы с системными свойствами
  11.         invoke  PSGetPropertySystem,IID_IPropertySystem,pPSys
  12.  
  13.         ; Получить список системных свойств
  14.         mov     eax,[pPSys]
  15.         mov     eax,[eax]
  16.         stdcall [eax+IPropertySystem.EnumeratePropertyDescriptions],[pPSys],\
  17.                 PDEF_VIEWABLE,\
  18.                 IID_IPropertyDescriptionList,pPropList
  19.  
  20.         ; Получить количество системных свойств
  21.         mov     eax,[pPropList]
  22.         mov     eax,[eax]
  23.         stdcall [eax+IPropertyDescriptionList.GetCount],[pPropList],\
  24.                 nProp
  25.  
  26.         ; Перебрать все свойства по очереди
  27.         xor     ebx,ebx
  28. loc_loop:
  29.         ; Получить очередное свойство
  30.         mov     eax,[pPropList]
  31.         mov     eax,[eax]
  32.         stdcall [eax+IPropertyDescriptionList.GetAt],[pPropList],\
  33.                 ebx,IID_IPropertyDescription,pProp
  34.  
  35.         or      eax,eax
  36.         jnz     loc_next
  37.  
  38.         ; Получить каноническое имя свойства
  39.         mov     eax,[pProp]
  40.         mov     eax,[eax]
  41.         stdcall [eax+IPropertyDescription.GetCanonicalName],[pProp],\
  42.                 lpCanon
  43.  
  44.         ; Получить отображаемое имя свойства
  45.         mov     eax,[pProp]
  46.         mov     eax,[eax]
  47.         stdcall [eax+IPropertyDescription.GetDisplayName],[pProp],\
  48.                 lpProp
  49.  
  50.         ; Получить и отформатировать строку значения свойства
  51.         invoke  PSFormatPropertyValue,[pStore],[pProp],PDFF_DEFAULT,lpVal
  52.  
  53.         ; Такое свойство есть у файла?
  54.         or      eax,eax
  55.         jnz     loc_next
  56.  
  57.         ...
  58.         ...
  59.         ; [lpCanon] -> каноническое имя
  60.         ; [lpProp] -> человекопонятное название
  61.         ; [lpVal] -> значение
  62.         ...
  63.         ...
  64.  
  65. loc_next:
  66.         ; Следующее свойство
  67.         inc     ebx
  68.         cmp     ebx,[nProp]
  69.         jb      loc_loop
  70.  
  71.         invoke  CoUninitialize
Для музыкальных файлов это будет длительность трека, наименование исполнителя, название композиции, причем описанный ранее косяк со слешем в названии тут автоматически нейтрализуется - слеш заменяется на точку с запятой, а название модифицируется. Результат получается, мягко говоря, не шедевр, но это все-таки лучше, чем просто обрезка строки по первому слешу. Для графики будут получены размеры изображения и плотность точек, названия камеры и использованного софта, дата съемки. Перечень данных существенно скромнее, чем если парсить секцию EXIF самостоятельно, но зато получается универсальное решение для подавляющего большинства графических форматов, причем даже если они неизвестны вашему приложению. Короче, у этого способа есть как плюсы, так и минусы. Использовать его или нет, и в какой мере, это вы уже решайте самостоятельно.

В приложении пример программы с исходным текстом, которая получает все доступные системные свойства из файла.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Generic.Metadata.Demo.zip (312,283 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 712 | Комментариев: 0

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.006 сек.) / Память: 4.5 Mb
Наверх