Таким образом, преодолено два ограничения VB:
- нельзя было вернуть положительный HRESULT, такой как S_FALSE;
- нельзя было вернуть некоторые конкретные значения HRESULT, которые VB в соответствии со своей внутренней логикой преобразовывал (например, E_OUTOFMEMORY = 0x8007000E в 0x800A007)
Задумываемая область применения этого способа - при имплементации интерфейсов, требующих необычных HRESULT-ов, удастся обойти без WriteProcessMemory и подстановки в VTbl адресов функций из обычных модулей.
Модуль:
- Код: Выделить всё
Option Explicit
Public Declare Function InterlockedExchange Lib "kernel32" (ByVal Target As Long, ByVal Value As Long) As Long
Public Declare Sub PutMem4 Lib "msvbvm60" (pDst As Any, ByVal Src As Any)
Public ReturnCode(10) As Byte
Sub Main()
'initialize thunk
ReturnCode(0) = &HB8
ReturnCode(5) = &H68
ReturnCode(10) = &HC3
Dim c As Class1
Set c = New Class1
c.Harmless 123
End Sub
Class1:
- Код: Выделить всё
Option Explicit
Public Sub Harmless(ByVal IgnoreMe As Long)
Debug.Print "Been here"
PutMem4 ReturnCode(1), &H80004001 'E_NOTIMPL
PutMem4 ReturnCode(6), InterlockedExchange(VarPtr(IgnoreMe) - 8, VarPtr(ReturnCode(0)))
End Sub