Работа с TypeLib на Ассемблере
Работа с TypeLib на Ассемблере
В предыдущей статье, посвященной программам для работы с TypeLib, я обещал рассказать о возможностях программного доступа к содержимому этих библиотек. Напомню, что в TypeLib или, если по-русски, в библиотеке типов содержится информация о COM-объектах, их свойствах и методах, константах, структурах и т.п. Тема большая и интересная, по крайней мере для меня.
Информации по данному вопросу в интернете практически нет, тем более касающейся работы с библиотеками типов на Ассемблере. Что-то удалось собрать по крупицам из разрозненных источников, что-то нашлось в исходниках, но большую часть пришлось разбирать самостоятельно. В статье я постараюсь осветить все основные принципы разбора TypeLib. Но сразу скажу, что разбор библиотек типов мне требуется в первую очередь для пополнения базы моих программ GUID Helper и Constant Helper, поэтому часть малозначащей, на мой взгляд, информации сознательно будет пропущена. При необходимости вы всегда можете дописать весь недостающий вам функционал на базе приведенного в статье кода.
Практически все тут будет основано на взаимодействии с COM, так что традиционно начинаем с описания здоровенной пачки интерфейсов, структур и констант, которые нам понадобятся для дальнейшей работы. Обратите внимание, что некоторые структуры приходится выравнивать до границы DWORD, иначе адресация будет работать неправильно. Что ж, несколько часов в отладчике стоили того, чтобы приобрести эти знания. А в официальной документации MSDN об этой важной особенности не сказано ни слова.
Code (Assembler) : Убрать нумерацию
- struct DECIMAL
- wReserved dw ?
- union
- struct
- scale db ?
- sign db ?
- ends
- signscale dw ?
- ends
- Hi32 dd ?
- union
- struct
- Lo32 dd ?
- Mid32 dd ?
- ends
- Lo64 dq ?
- ends
- ends
- struct VARIANT
- union
- struct
- vt dw ?
- wReserved rw 3
- union
- llVal dq ?
- lVal dd ?
- iVal dw ?
- bVal db ?
- ends
- ends
- decVal DECIMAL
- ends
- ends
- ; ITypeLib Interface
- struct ITypeLib
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; ITypeLib
- GetTypeInfoCount dd ? ; 00Ch
- GetTypeInfo dd ? ; 010h
- GetTypeInfoType dd ? ; 014h
- GetTypeInfoOfGuid dd ? ; 018h
- GetLibAttr dd ? ; 01Ch
- GetTypeComp dd ? ; 020h
- GetDocumentation dd ? ; 024h
- IsName dd ? ; 028h
- FindName dd ? ; 02Ch
- ReleaseTLibAttr dd ? ; 030h
- ends
- ; ITypeInfo Interface
- struct ITypeInfo
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; ITypeInfo
- GetTypeAttr dd ? ; 00Ch
- GetTypeComp dd ? ; 010h
- GetFuncDesc dd ? ; 014h
- GetVarDesc dd ? ; 018h
- GetNames dd ? ; 01Ch
- GetRefTypeOfImplType dd ? ; 020h
- GetImplTypeFlags dd ? ; 024h
- GetIDsOfNames dd ? ; 028h
- _Invoke dd ? ; 02Ch
- GetDocumentation dd ? ; 030h
- GetDllEntry dd ? ; 034h
- GetRefTypeInfo dd ? ; 038h
- AddressOfMember dd ? ; 03Ch
- CreateInstance dd ? ; 040h
- GetMops dd ? ; 044h
- GetContainingTypeLib dd ? ; 048h
- ReleaseTypeAttr dd ? ; 04Ch
- ReleaseFuncDesc dd ? ; 050h
- ReleaseVarDesc dd ? ; 054h
- ends
- struct TYPEDESC
- union
- lptdesc dd ?
- lpadesc dd ?
- hreftype dd ?
- ends
- vt dw ?
- dw ?
- ends
- struct PARAMDESC
- pparamdescex dd ?
- wParamFlags dw ?
- dw ?
- ends
- struct IDLDESC
- dwReserved dd ?
- wIDLFlags dw ?
- dw ?
- ends
- struct ELEMDESC
- tdesc TYPEDESC
- union
- idldesc IDLDESC
- paramdesc PARAMDESC
- ends
- ends
- struct SAFEARRAYBOUND
- cElements dd ?
- lLbound dd ?
- ends
- struct ARRAYDESC
- tdescElem TYPEDESC
- cDims dw ?
- dw ?
- rgbounds SAFEARRAYBOUND
- ends
- struct TYPEATTR
- guid rb 16
- lcid dd ?
- dwReserved dd ?
- memidConstructor dd ?
- memidDestructor dd ?
- lpstrSchema dd ?
- cbSizeInstance dd ?
- typekind dd ?
- cFuncs dw ?
- cVars dw ?
- cImplTypes dw ?
- cbSizeVft dw ?
- cbAlignment dw ?
- wTypeFlags dw ?
- wMajorVerNum dw ?
- wMinorVerNum dw ?
- tdescAlias TYPEDESC
- idldescType IDLDESC
- ends
- struct VARDESC
- memid dd ?
- lpstrSchema dd ?
- union
- oInst dd ?
- lpvarValue dd ?
- ends
- elemdescVar ELEMDESC
- wVarFlags dw ?
- dw ?
- varkind dd ?
- ends
- struct FUNCDESC
- memid dd ?
- lprgscode dd ?
- lprgelemdescParam dd ?
- funckind dd ?
- invkind dd ?
- callconv dd ?
- cParams dw ?
- cParamsOpt dw ?
- oVft dw ?
- cScodes dw ?
- elemdescFunc ELEMDESC
- wFuncFlags dw ?
- dw ?
- ends
Code (Assembler) : Убрать нумерацию
- VT_EMPTY = 0
- VT_NULL = 1
- VT_I2 = 2
- VT_I4 = 3
- VT_R4 = 4
- VT_R8 = 5
- VT_CY = 6
- VT_DATE = 7
- VT_BSTR = 8
- VT_DISPATCH = 9
- VT_ERROR = 10
- VT_BOOL = 11
- VT_VARIANT = 12
- VT_UNKNOWN = 13
- VT_DECIMAL = 14
- VT_I1 = 16
- VT_UI1 = 17
- VT_UI2 = 18
- VT_UI4 = 19
- VT_I8 = 20
- VT_UI8 = 21
- VT_INT = 22
- VT_UINT = 23
- VT_VOID = 24
- VT_HRESULT = 25
- VT_PTR = 26
- VT_SAFEARRAY = 27
- VT_CARRAY = 28
- VT_USERDEFINED = 29
- VT_LPSTR = 30
- VT_LPWSTR = 31
- VT_RECORD = 36
- VT_INT_PTR = 37
- VT_UINT_PTR = 38
- VT_FILETIME = 64
- VT_BLOB = 65
- VT_STREAM = 66
- VT_STORAGE = 67
- VT_STREAMED_OBJECT = 68
- VT_STORED_OBJECT = 69
- VT_BLOB_OBJECT = 70
- VT_CF = 71
- VT_CLSID = 72
- VT_VERSIONED_STREAM = 73
- VT_STORED_PROPSET = 74
- VT_BLOB_PROPSET = 75
- VT_VERBOSE_ENUM = 76
- VT_BSTR_BLOB = 0x0FFF
- VT_VECTOR = 0x1000
- VT_ARRAY = 0x2000
- VT_BYREF = 0x4000
- VT_RESERVED = 0x8000
- VT_ILLEGAL = 0xFFFF
- VT_ILLEGALMASKED = 0x0FFF
- VT_TYPEMASK = 0x0FFF
- MAX_NAMES = 64
- REGKIND_NONE = 2
- TKIND_ENUM = 0
- TKIND_RECORD = 1
- TKIND_MODULE = 2
- TKIND_INTERFACE = 3
- TKIND_DISPATCH = 4
- TKIND_COCLASS = 5
- TKIND_ALIAS = 6
- TKIND_UNION = 7
- INVOKE_FUNC = 1
- INVOKE_PROPERTYGET = 2
- INVOKE_PROPERTYPUT = 4
- INVOKE_PROPERTYPUTREF = 8
- VAR_PERINSTANCE = 0
- VAR_CONST = 2
- MEMBERID_NIL = -1
- PARAMFLAG_NONE = 0
- PARAMFLAG_FIN = 0x1
- PARAMFLAG_FOUT = 0x2
- PARAMFLAG_FLCID = 0x4
- PARAMFLAG_FRETVAL = 0x8
- PARAMFLAG_FOPT = 0x10
Первым делом получим название и описание библиотеки с помощью метода GetDocumentation, а также через метод GetTypeInfoCount узнаем количество записей, которые в ней содержатся.
Code (Assembler) : Убрать нумерацию
- ; Загрузить библиотеку без регистрации
- invoke LoadTypeLibEx,szFile,REGKIND_NONE,pptlib
- ; Получить имя и описание библиотеки
- mov eax, [pptlib]
- mov eax, [eax]
- stdcall dword [eax+ITypeLib.GetDocumentation],[pptlib],\
- MEMBERID_NIL,strName,strDoc,NULL,NULL
- ; [strName] - указатель на строку названия библиотеки
- ; [strDoc] - указатель на строку описания, может быть пустым
- ; Прибраться за собой
- invoke SysFreeString,[strName]
- invoke SysFreeString,[strDoc]
- ; Получить количество элементов
- mov eax, [pptlib]
- mov eax, [eax]
- stdcall dword [eax+ITypeLib.GetTypeInfoCount],[pptlib]
- ; EAX - количество записей в библиотеке
Code (Assembler) : Убрать нумерацию
- ; Обработать каждый элемент по очереди
- mov [num],0
- loc_loop:
- ; Получить информацию о типе элемента
- mov eax, [pptlib]
- mov eax, [eax]
- stdcall dword [eax+ITypeLib.GetTypeInfo],[pptlib],\
- [num],iInfo
- ; Удалось определить тип?
- or eax,eax
- ; Нет, переходим к следующему
- jnz loc_next
- ; Получить свойства элемента
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetTypeAttr],[iInfo],\
- pTypeAttr
- ; Удалось получить свойства элемента?
- or eax,eax
- ; Да, обрабатываем его
- jz @f
- ; Прибраться за собой
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.Release],[iInfo]
- ; Переходим к следующему элементу
- jmp loc_next
- @@:
- ;----------------------------------
- ; Обработка элемента
- ;----------------------------------
- loc_clear:
- ; Прибраться за собой
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.ReleaseTypeAttr],[iInfo],[pTypeAttr]
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.Release],[iInfo]
- loc_next:
- ; Все элементы библиотеки обработаны?
- inc [num]
- mov eax,[num]
- cmp eax,[nCount]
- jb loc_loop
- ; Прибраться за собой
- mov eax, [pptlib]
- mov eax, [eax]
- stdcall dword [eax+ITypeLib.Release],[pptlib]
C помощью уже знакомого нам метода GetDocumentation получаем название элемента и описание, если оно есть. Из структуры TYPEATTR извлекаем нужные поля, обязательно нужно значение typekind, а остальное на ваше усмотрение, в частности меня интересует еще поле GUID. Если это поле не пустое, то его можно преобразовать в строку при помощи штатной функции StringFromGUID2.
Code (Assembler) : Убрать нумерацию
- ; Получить имя и описание элемента
- mov eax, [pptlib]
- mov eax, [eax]
- stdcall dword [eax+ITypeLib.GetDocumentation],[pptlib],\
- [num],strName,strDoc,NULL,NULL
- ; [strName] - указатель на строку названия элемента
- ; [strDoc] - указатель на строку описания, может быть пустым
- ; Прибраться за собой
- invoke SysFreeString,[strName]
- invoke SysFreeString,[strDoc]
- ; Указатель на структуру TYPEATTR
- mov esi,[pTypeAttr]
- ; [esi+TYPEATTR.typekind] - тип элемента
- ; [esi+TYPEATTR.guid] - GUID элемента, может быть пустым
- ;----------------------------------
- ; Обработка элемента в зависимости
- ; от его типа
- ;----------------------------------
Code (Assembler) : Убрать нумерацию
- ; Это перечисление?
- cmp [esi+TYPEATTR.typekind],TKIND_ENUM
- jne loc_not_enum
- ; Количество элементов в перечислении
- movzx eax,[esi+TYPEATTR.cVars]
- or eax,eax
- jz loc_not_enum
- mov [num2],0
- loc_loop_enum:
- ; Получить структуру VARDESC, описывающую переменную
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetVarDesc],[iInfo],\
- [num2],pVarDesc
- ; Указатель на структуру VARDESC
- mov edi,[pVarDesc]
- ; Получить название переменной
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetDocumentation],[iInfo],\
- [edi+VARDESC.memid],strName,NULL,NULL,NULL
- ; Получить значение переменной
- mov eax,[edi+VARDESC.lpvarValue]
- mov eax,[eax+VARIANT.lVal]
- ; [strName] - указатель на название переменной
- ; EAX = значение переменной
- ; Прибраться за собой
- invoke SysFreeString,[strName]
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.ReleaseVarDesc],[iInfo],[pVarDesc]
- ; Все значения в перечислении обработаны?
- inc [num2]
- mov eax,[num2]
- cmp ax,[esi+TYPEATTR.cVars]
- jb loc_loop_enum
Элемент типа TKIND_ALIAS является псевдонимом для другого типа. Тут требуется узнать название этого самого другого типа. Для этого надо декодировать структуру TYPEDESC, которая содержится в поле tdescAlias структуры TYPEATTR. Функция декодирования будет описана ниже.
Code (Assembler) : Убрать нумерацию
- ; Это алиас?
- cmp [esi+TYPEATTR.typekind],TKIND_ALIAS
- jne loc_not_alias
- ; Тип алиаса
- lea eax,[esi+TYPEATTR.tdescAlias.lptdesc]
- stdcall DecodeType,eax,strType
Code (Assembler) : Убрать нумерацию
- ; Это класс?
- cmp [esi+TYPEATTR.typekind],TKIND_COCLASS
- jne loc_not_class
- ; Количество реализованных интерфейсов
- movzx eax,[esi+TYPEATTR.cImplTypes]
- or eax,eax
- jz loc_not_class
- mov [num2],0
- loc_loop_class:
- ; Получить информацию об интерфейсе
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetRefTypeOfImplType],[iInfo],\
- [num2],pRefType
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetRefTypeInfo],[iInfo],\
- [pRefType],pType2
- ; Получить название интерфейса
- mov eax,[pType2]
- mov eax,[eax]
- stdcall dword [eax+ITypeInfo.GetDocumentation],[pType2],\
- MEMBERID_NIL,strRName,NULL,NULL,NULL
- ; [strRName] - название интерфейса
- ; Прибраться за собой
- invoke SysFreeString,[strRName]
- mov eax,[pType2]
- mov eax,[eax]
- stdcall dword [eax+ITypeInfo.Release],[pType2]
- ; Все интерфейсы обработаны?
- inc [num2]
- mov eax,[num2]
- cmp ax,[esi+TYPEATTR.cImplTypes]
- jb loc_loop_class
Code (Assembler) : Убрать нумерацию
- ; Это интерфейс?
- cmp [esi+TYPEATTR.typekind],TKIND_INTERFACE
- je @f
- cmp [esi+TYPEATTR.typekind],TKIND_DISPATCH
- je @f
- ; Это структура или объединение?
- cmp [esi+TYPEATTR.typekind],TKIND_UNION
- je @f
- cmp [esi+TYPEATTR.typekind],TKIND_RECORD
- jne loc_not_func
- @@:
- ; Количество свойств
- movzx eax,[esi+TYPEATTR.cVars]
- or eax,eax
- jz loc_no_prop
- mov [num2],0
- loc_loop_prop:
- ; Получить информацию о свойстве
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetVarDesc],[iInfo],\
- [num2],pVarDesc
- ; Указатель на структуру VARDESC
- mov edi,[pVarDesc]
- ; Название свойства и описание
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetDocumentation],[iInfo],\
- [edi+VARDESC.memid],strName,strDoc,NULL,NULL
- ; [strName] - указатель на строку названия свойства
- ; [strDoc] - указатель на строку описания, может быть пустым
- ; Прибраться за собой
- invoke SysFreeString,[strName]
- invoke SysFreeString,[strDoc]
- ; Тип свойства
- lea eax,[edi+VARDESC.elemdescVar.tdesc]
- stdcall DecodeType,eax,strType
- ; strType - строка с типом свойства
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.ReleaseVarDesc],[iInfo],[pVarDesc]
- ; Все данные в перечислении обработаны?
- inc [num2]
- mov eax,[num2]
- cmp ax,[esi+TYPEATTR.cVars]
- jb loc_loop_prop
- loc_no_prop:
Code (Assembler) : Убрать нумерацию
- ; Количество методов
- movzx eax,[esi+TYPEATTR.cFuncs]
- or eax,eax
- jz loc_not_func
- mov [num2],0
- loc_loop_func:
- ; Получить информацию о методе
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetFuncDesc],[iInfo],\
- [num2],pFuncDesc
- ; Указатель на структуру FUNCDESC
- mov edi,[pFuncDesc]
- ; Получить имя метода и описание
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetDocumentation],[iInfo],\
- [edi+FUNCDESC.memid],strName,strDoc,NULL,NULL
- ; [strName] - указатель на строку названия метода
- ; [strDoc] - указатель на строку описания, может быть пустым
- ; Прибраться за собой
- invoke SysFreeString,[strName]
- invoke SysFreeString,[strDoc]
- ; Тип возврата функции
- lea eax,[edi+FUNCDESC.elemdescFunc.tdesc]
- stdcall DecodeType,eax,strType
- ; strType - строка с типом возврата
- ; У функции есть параметры?
- cmp [edi+FUNCDESC.cParams],0
- je func_no_params
- ; Получить названия всех параметров
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.GetNames],[iInfo],\
- [edi+FUNCDESC.memid],pnames,MAX_NAMES,tmp
- mov [num3],0
- loc_loop_param:
- ; Следующий параметр в массиве
- mov eax,[num3]
- shl eax,4
- mov ebx,[edi+FUNCDESC.lprgelemdescParam]
- add ebx,eax
- ; Какие-то флаги у параметра функции имеются?
- cmp word[ebx+ELEMDESC.paramdesc.wParamFlags],PARAMFLAG_NONE
- je loc_no_flags
- ;----------------------------------
- ; Обработать флаги параметра
- ;----------------------------------
- loc_no_flags:
- ; Получить название параметра из массива
- mov eax,[num3]
- inc eax
- shl eax,2
- mov eax,[pnames+eax]
- ; EAX - указатель на название параметра
- ; Получить тип параметра
- stdcall DecodeType,ebx,strType
- ; strType - строка с типом параметра
- ; Все параметры функции обработаны?
- inc [num3]
- mov eax,[num3]
- cmp ax,[edi+FUNCDESC.cParams]
- jb loc_loop_param
- func_no_params:
- ; Прибраться за собой
- mov eax, [iInfo]
- mov eax, [eax]
- stdcall dword [eax+ITypeInfo.ReleaseFuncDesc],[iInfo],[pFuncDesc]
- ; Все методы обработаны?
- inc [num2]
- mov eax,[num2]
- cmp ax,[esi+TYPEATTR.cFuncs]
- jb loc_loop_func
- loc_not_func:
Ну и наконец не раз упомянутая выше вспомогательная функция. Она декодирует данные, содержащиеся в структуре TYPEDESC, корректно обрабатываются частные случаи, такие как указатели на значение, указатели на указатели на значение, пользовательские типы данных и массивы. Для остальных значений типа VARIANT коды преобразовываются в их общепринятые текстовые названия. При появлении новых типов достаточно будет просто дополнить список кодов и их названий. В качестве параметров функции передаются указатель на структуру TYPEDESC и указатель на строку-приемник декодированных данных.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------
- ; Функция декодирования данных из структуры TYPEDESC
- ;------------------------------------------------------------
- proc DecodeType ptdesc:DWORD,lpStr:DWORD
- pusha
- mov esi,[ptdesc]
- movzx eax,[esi+TYPEDESC.vt]
- ; Это указатель?
- cmp eax,VT_INT_PTR
- je @f
- cmp eax,VT_UINT_PTR
- je @f
- cmp eax,VT_PTR
- jne .loc_no_ptr
- @@:
- ; Рекурсивно вызвать функцию с указываемым типом данных
- stdcall DecodeType,[esi+TYPEDESC.lptdesc],[lpStr]
- ; Добавить символ указателя
- invoke lstrcat,[lpStr],.ref
- jmp .loc_ret
- .loc_no_ptr:
- ; Это массив?
- cmp eax,VT_CARRAY
- jne .loc_no_carray
- ; ARRAYDESC
- mov esi,[esi+TYPEDESC.lpadesc]
- stdcall DecodeType,esi,[lpStr]
- ; Перебрать строки массива
- mov [num4],0
- .loc_loop_dim:
- ; Количество элементов в строке массива
- mov eax,[num4]
- shl eax,4
- invoke wsprintf,buff,szMask11,[esi+ARRAYDESC.rgbounds.cElements+eax]
- add esp,12
- invoke lstrcat,[lpStr],buff
- ; Все строки массива обработали?
- inc [num4]
- mov eax,[num4]
- cmp ax,word [esi+ARRAYDESC.cDims]
- jb .loc_loop_dim
- jmp .loc_ret
- .loc_no_carray:
- ; Это пользовательские данные?
- cmp eax,VT_USERDEFINED
- jne .loc_no_user
- ; Получить информацию о данных
- mov eax,[iInfo]
- mov eax,[eax]
- stdcall dword [eax+ITypeInfo.GetRefTypeInfo],[iInfo],\
- [esi+TYPEDESC.hreftype],pRefType
- ; Получить название пользовательских данных
- mov eax,[pRefType]
- mov eax,[eax]
- stdcall dword [eax+ITypeInfo.GetDocumentation],[pRefType],\
- MEMBERID_NIL,strRName,NULL,NULL,NULL
- invoke lstrcat,[lpStr],[strRName]
- ; Прибраться за собой
- invoke SysFreeString,[strRName]
- mov eax,[pRefType]
- mov eax,[eax]
- stdcall dword [eax+ITypeInfo.Release],[pRefType]
- jmp .loc_ret
- .loc_no_user:
- ; Преобразовать код VT_xx в текстовый вид
- movzx ebx,[esi+TYPEDESC.vt]
- mov esi,.vtable
- .loc_loop:
- lodsd
- cmp eax,0xFFFFFFFF
- je @f
- cmp eax,ebx
- je .loc_set
- invoke lstrlen,esi
- inc eax
- shl eax,1
- add esi,eax
- jmp .loc_loop
- @@:
- mov esi,.error
- .loc_set:
- invoke lstrcat,[lpStr],esi
- .loc_ret:
- popa
- ret
- .ref du '*',0
- .error du 'Unknown type',0
- .vtable dd VT_EMPTY
- du 'void',0
- dd VT_NULL
- du 'NULL',0
- dd VT_I2
- du 'short',0
- dd VT_I4
- du 'long',0
- dd VT_R4
- du 'single',0
- dd VT_R8
- du 'double',0
- dd VT_CY
- du 'CURRENCY',0
- dd VT_DATE
- du 'DATE',0
- dd VT_BSTR
- du 'BSTR',0
- dd VT_DISPATCH
- du 'IDispatch*',0
- dd VT_ERROR
- du 'SCODE',0
- dd VT_BOOL
- du 'BOOL',0
- dd VT_VARIANT
- du 'VARIANT',0
- dd VT_UNKNOWN
- du 'IUnknown*',0
- dd VT_I1
- du 'char',0
- dd VT_UI1
- du 'unsigned char',0
- dd VT_UI2
- du 'unsigned short',0
- dd VT_UI4
- du 'unsigned long',0
- dd VT_I8
- du 'int64',0
- dd VT_UI8
- du 'uint64',0
- dd VT_INT
- du 'int',0
- dd VT_UINT
- du 'unsigned int',0
- dd VT_VOID
- du 'void',0
- dd VT_HRESULT
- du 'HRESULT',0
- dd VT_PTR
- du 'void*',0
- dd VT_SAFEARRAY
- du 'SAFEARRAY',0
- dd VT_CARRAY
- du 'CARRAY',0
- dd VT_USERDEFINED
- du 'USERDEFINED',0
- dd VT_LPSTR
- du 'LPSTR',0
- dd VT_LPWSTR
- du 'LPWSTR',0
- dd VT_FILETIME
- du 'FILETIME',0
- dd VT_BLOB
- du 'BLOB',0
- dd VT_STREAM
- du 'STREAM',0
- dd VT_STORAGE
- du 'STORAGE',0
- dd VT_STREAMED_OBJECT
- du 'STREAMED_OBJECT',0
- dd VT_STORED_OBJECT
- du 'STORED_OBJECT',0
- dd VT_BLOB_OBJECT
- du 'BLOB_OBJECT',0
- dd VT_CF
- du 'CF',0
- dd VT_CLSID
- du 'CLSID',0
- dd VT_VERSIONED_STREAM
- du 'VERSIONED_STREAM',0
- dd VT_STORED_PROPSET
- du 'STORED_PROPSET',0
- dd VT_BLOB_PROPSET
- du 'BLOB_PROPSET',0
- dd VT_VERBOSE_ENUM
- du 'VERBOSE_ENUM',0
- dd 0xFFFFFFFF
- endp
В приложении пример программы с исходным текстом, которая разбирает данные из библиотеки TypeLib и выводит их в текстовом виде.
Просмотров: 214 | Комментариев: 0
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария