Нужен интерфейс с методом write(vStr as Variant)

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 02.07.2007 (Пн) 13:13

Да тут настоящая вакханалия мысли развернулась :)
tyomitch писал(а):Гы, не удержался-таки :-))
Это вроде замена имени метода, а не перенаправление вызова... В принципе подойдет, но с интерфейсами как-то красивее. А как это будет выглядеть для двух и более методов? Или метода и свойства? К примеру Public Property Input.
Лучший способ понять что-то самому — объяснить это другому.

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 02.07.2007 (Пн) 13:16

Antonariy
У меня это будет выглядеть добавлением ещё нескольких имён. В способе с перехватом GetIDsOfNames придётся изменить ещё несколько строк.
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 02.07.2007 (Пн) 13:22

Antonariy писал(а):В принципе подойдет, но с интерфейсами как-то красивее.

VB6 по запросу IDispatch отдаст только главный диспинтерфейс, сколько бы ни было дополнительных.
Т.е. красиво-то красиво, только это тупик :-(

Antonariy писал(а):А как это будет выглядеть для двух и более методов? Или метода и свойства? К примеру Public Property Input.


Для двух методов:
Код: Выделить всё
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function VirtualProtect Lib "kernel32" (lpAddress As Any, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
Private Declare Function lstrcmpiW Lib "kernel32" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long
Private Const PAGE_EXECUTE_READWRITE = &H40

Public Function Anything() As String
    Anything = "Mary had a little lamb"
End Function

Public Sub Write_(ByVal vStr As Variant)
    MsgBox vStr
End Sub

Public Sub Close_()
    MsgBox "Closed"
End Sub

Private Sub GetIDsOfNamesReplacement(ByVal riid As Long, rgszNames As Long, ByVal cNames As Long, ByVal lcid As Long, ByVal rgDispId As Long)
If 0 = lstrcmpiW(rgszNames, StrPtr("Write")) Then
    ReDim Names(cNames) As Long
    CopyMemory Names(0), rgszNames, cNames * 4
    Names(0) = StrPtr("Write_")
    Call GetIDsOfNamesOriginal(riid, Names(0), cNames, lcid, rgDispId)
ElseIf 0 = lstrcmpiW(rgszNames, StrPtr("Close")) Then
    ReDim Names(cNames) As Long
    CopyMemory Names(0), rgszNames, cNames * 4
    Names(0) = StrPtr("Close_")
    Call GetIDsOfNamesOriginal(riid, Names(0), cNames, lcid, rgDispId)
Else
    Call GetIDsOfNamesOriginal(riid, rgszNames, cNames, lcid, rgDispId)
End If
End Sub

Private Sub GetIDsOfNamesOriginal(ByVal riid As Long, rgszNames As Long, ByVal cNames As Long, ByVal lcid As Long, ByVal rgDispId As Long)
'Never called
End Sub

Private Sub Class_Initialize()
Dim pVTbl As Long, OldProtect As Long
    CopyMemory pVTbl, ByVal ObjPtr(Me), 4
    VirtualProtect ByVal pVTbl, 44, PAGE_EXECUTE_READWRITE, OldProtect
    If OldProtect = PAGE_EXECUTE_READWRITE Then Exit Sub
    CopyMemory ByVal pVTbl + 44, ByVal pVTbl + 20, 4
    CopyMemory ByVal pVTbl + 20, ByVal pVTbl + 40, 4
End Sub

Далее аналогично.

Поскольку это простая подмена имени, то тип метода (свойство, не свойство) ни на что не влияет.
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 02.07.2007 (Пн) 13:55

VB6 по запросу IDispatch отдаст только главный диспинтерфейс, сколько бы ни было дополнительных.
Т.е. красиво-то красиво, только это тупик
А-а. Мне просто показалось, что
Остаётся только вызов IDispatch::GetIDsOfNames перехватывать, чтобы вызовы метода "Write" перенаправлять на собственный соседний интерфейс.
относится как раз к интерфейсам.

keks-n
Спасибо за ликбез, враппер тоже пригодится.
Лучший способ понять что-то самому — объяснить это другому.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 02.07.2007 (Пн) 13:58

Antonariy писал(а):А-а. Мне просто показалось, что
Остаётся только вызов IDispatch::GetIDsOfNames перехватывать, чтобы вызовы метода "Write" перенаправлять на собственный соседний интерфейс.
относится как раз к интерфейсам.

Нет, так тоже можно. Только чем это будет красивее? Кода больше (всё равно патчить VTbl надо), а толку столько же.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 02.07.2007 (Пн) 14:26

NashRus
Скажи своему экзотическому Mail-провайдеру, чтобы разбанил адрес 194.67.52.99.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

NashRus
Постоялец
Постоялец
 
Сообщения: 388
Зарегистрирован: 18.03.2006 (Сб) 1:16

Сообщение NashRus » 02.07.2007 (Пн) 22:55

Хакер
хотел что-то скинуть или что ?

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 02.07.2007 (Пн) 23:56

Кстати, есть способ получить IDispatch конкретного интерфейса.
1) Объявляем 3 переменные: a As Object, b As имя_интерфейса, zero As Long
2) Присваиваем к b объект
3) Делаем
Set a=Nothing
CopyMemory a,b,4
zero=0
CopyMemory b,zero,4
Set b=a


В итоге у нас в a лежит IDispatch интерфейса из переменной b и не было потери счётчика ссылок. Естественно, интерфейс из переменной b должен наследоваться от IDispatch
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 03.07.2007 (Вт) 3:08

NashRus
Форум хочет скидывать тебе уведомления об ответах и личных сообщениях. И всякий раз мне приходит письмо, в котором говрится что на starnet.ru забанен VBStreets-овский SMTP-сервер.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

NashRus
Постоялец
Постоялец
 
Сообщения: 388
Зарегистрирован: 18.03.2006 (Сб) 1:16

Сообщение NashRus » 03.07.2007 (Вт) 8:08

2Хакер,

понятно. думал сейчас кодом разживусь :roll:

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.07.2007 (Вт) 8:32

keks-n писал(а):Кстати, есть способ получить IDispatch конкретного интерфейса.

Есть даже более простой: Set b = a.

Проблема в том, что клиент, которому эта ссылка будет передана, вызовет на ней QueryInterface(IID_IDispatch), и получит всё равно главный интерфейс.
Изображение

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 03.07.2007 (Вт) 11:31

Ясно... А там As Variant, что-ли?
Изображение

Пред.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот и гости: 103

    TopList