<html>
<head>
<script language="vbscript">
//{Public Const==============================================
Public Const HEAP_ZERO_MEMORY = &h00000008
Public Const PAGE_EXECUTE_READWRITE = &h40
Public Const S_OK = &h0
Public Const E_NOINTERFACE = &h80004002
Public Const IID_IUnknown = "{00000000-0000-0000-C000-000000000046}"
Public Const IID_IHTMLDocument2 = "{332C4425-26CB-11D0-B483-00C04FD90119}"
Public Const IID_IOleObject = "{00000112-0000-0000-C000-000000000046}"
Public Const CLSID_Outlook = "{261B8CA9-3BAF-4BD0-B0C2-BF04286785C6}"
Public Const IID_IClassFactory = "{00000001-0000-0000-C000-000000000046}"
Public Const IID_IViewCtl = "{00067274-0000-0000-C000-000000000046}"
Public Const IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"
Public Const HKEY_CLASSES_ROOT = &h80000000
//}==========================================================
//{Public Vars==============================================
Public Wrap
Set Wrap = CreateObject("DynamicWrapperX")
Public oServ
Public buf
Public swIID
Public pCLSID
Public pIID
Public ppv
Public ppOle
Public res
Public pIClassFactory
Public pOleContainer
Public pIOleObject
Public Addr1
Public oldAddr1
Public Addr2
Public oldAddr2
Public Addr3
//}==========================================================
//{Class Service==============================================
Class Service
Private hHeap
Private Ref1
Private Ref2
Private dbuf
Private pIID_Disp
Private AddrCoGet
//{Class_Initialize
Private Sub Class_Initialize
Wrap.Register "Kernel32", "VirtualProtect" , "i=lllp", "r=l"
Wrap.Register "Kernel32", "GetProcessHeap", "r=l"
Wrap.Register "Kernel32", "HeapAlloc", "i=lll", "r=l"
Wrap.Register "Kernel32", "HeapFree", "i=lll","r=l"
Wrap.Register "Advapi32", "RegOpenKey", "i=hsp","r=l"
Wrap.Register "Advapi32", "RegQueryValue", "i=hlpl","r=l"
Wrap.Register "Ole32" , "StringFromGUID2", "i=ppl", "r=l"
Wrap.Register "Ole32" , "IIDFromString", "i=pp", "r=l"
Wrap.Register "Ole32" , "CoMarshalInterThreadInterfaceInStream", "i=ppp", "r=l"
AddrCoGet = Wrap.Register("Ole32" , "CoGetInterfaceAndReleaseStream", "i=ppp", "r=l")
AddrCoGet = Wrap.NumGet(AddrCoGet, &h14) //адрес ф-ии CoGetInterfaceAndReleaseStream
hHeap = Wrap.GetProcessHeap()
res = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
swIID = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 256)
pIID = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 16)
pCLSID = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 16)
ppv = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
ppOle = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 4)
dbuf = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 100)
Wrap.VirtualProtect dbuf, 100, PAGE_EXECUTE_READWRITE, res
pIID_Disp = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 16)
//'Буфер под вызовы
buf = Wrap.HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 5)
Wrap.NumPut &hE9, buf, 0, "b" //'jmp ...Addr
//'IUnknown
Wrap.RegisterAddr buf, "IUnknown_QueryInterface", "i=ppp", "r=l" //'IUnknown::QueryInterface
Wrap.RegisterAddr buf, "IUnknown_AddRef", "i=p", "r=l" //'IUnknown::AddRef
Wrap.RegisterAddr buf, "IUnknown_Release", "i=p", "r=l" //'IUnknown::Release
//'IOleClientSite
Wrap.RegisterAddr buf, "IOleClientSite_GetContainer", "i=pp", "r=l" //'IOleClientSite::GetContainer
//'IClassFactory
Wrap.RegisterAddr buf, "IClassFactory_CreateInstance", "i=pppp", "r=l" //'IClassFactory::CreateInstance
//'IOleObject
Wrap.RegisterAddr buf, "IOleObject_SetClientSite", "i=pp", "r=l" //'IOleObject::SetClientSite
Set Ref1 = GetRef("IUnknown_QueryInterface")
Addr1 = Wrap.RegisterCallback(Ref1, "i=ppp", "r=l")
Set Ref2 = GetRef("IOleObject_SetClientSite")
Addr2 = Wrap.RegisterCallback(Ref2, "i=pp", "r=l")
// Адреса параметров у вспомогательных ф-й DWX
params1 = Wrap.NumGet(Addr1, 4)
params2 = Wrap.NumGet(Addr2, 4)
// Адреса IDispatch объектов VBS, через которые вызываются ф-и скрипта
pRef1 = Wrap.NumGet(params1, 0)
pRef2 = Wrap.NumGet(params2, 0)
Wrap.IIDFromString IID_IDispatch, pIID_Disp
// Заворачиваем для передачи в другую нить
Wrap.CoMarshalInterThreadInterfaceInStream pIID_Disp, pRef1, ppv
pStm1 = Wrap.NumGet(ppv)
Wrap.CoMarshalInterThreadInterfaceInStream pIID_Disp, pRef2, ppv
pStm2 = Wrap.NumGet(ppv)
// main - я так назвал ф-ю из DWX, через которую проходят Callback-вызовы
Offset = Wrap.NumGet(Addr2, 8 + 1) // относительный адрес ф-и 'main'
AddrMain = Addr2 + 8 + 5 + Offset // абсолютный адрес ф-и 'main'
//========================================================
// Этот код будет вызван вместо IOleObject::SetClientSite
// Сначала получим контейнер IOleClientSite::GetContainer.
// Далее передадим управление CallBack-функции из скрипта.
// Почему в скрипте не вызвать IOleClientSite::GetContainer? -
// Через скрипт мы контейнер не получим,
// т.к. в IOleClientSite::GetContainer сравниваются id нитей
// и если они не равны, возвращается E_UNEXPECTED
Wrap.NumPut &h0824448b, dbuf, 0 // mov eax, [esp+08] pClientSite
Wrap.NumPut &h68, dbuf, 4, "b" // push ppOle сюда должен прилететь IOleContainer
Wrap.NumPut ppOle, dbuf, 5
Wrap.NumPut &h50, dbuf, 9, "b" // push eax указатель на объект IOleClientSite
Wrap.NumPut &h008b, dbuf, 10, "n" // mov eax, [eax] vtable IOleClientSite
Wrap.NumPut &h0408b, dbuf, 12, "n" // mov eax, [eax+14] адрес IOleClientSite::GetContainer
Wrap.NumPut &h14, dbuf, 14, "b"
Wrap.NumPut &hD0FF, dbuf, 15, "n" // call [eax] IOleClientSite::GetContainer
Wrap.NumPut &hE9, dbuf, 17, "b" // jmp Addr2 адрес вспом. ф-и, для вызова IOleObject::SetClientSite
Wrap.NumPut (Addr2 - (dbuf + 17 + 5)), dbuf, 18
Addr3 = dbuf
//========================================================
// Перед вызовом вспомогательной ф-и DWX, которая в свою очередь вызывает
// ф-и VBS, вставим код, который развернет объекты VBS в другой нити.
// Подготавливаем код для перехвата (программируем в кодах)
// этот участок кода будет вызван 1 раз в другой нити,
// в нем разворачиваются дисп-интерфейсы VBS и заменяются в Callback-функциях.
//========================================================
preCode 22, pStm1, params1
preCode 22 + 30, pStm2, params2
// вот мы подменяем вызов на участок нового кода
Wrap.NumPut (dbuf + 22) - (Addr2 + 8 + 5), Addr2, 8 + 1
// возвращаем управление ф-и main
// при этом, объекты VBS уже изменены
Wrap.NumPut &hE9, dbuf, 82, "b" // jmp main
Wrap.NumPut (AddrMain - (dbuf + 82 + 5)), dbuf, 83
//========================================================
pOleContainer = 0
End Sub
//}
//Prepare code
Private Function preCode(offset, pStm, params)
// это вызов CoGetInterfaceAndReleaseStream
// результат помещаем в params
Wrap.NumPut &h68, dbuf, offset, "b" // push ppv
Wrap.NumPut ppv, dbuf, offset + 1
Wrap.NumPut &h68, dbuf, offset + 5, "b" // push IID_Dispatch
Wrap.NumPut pIID_Disp, dbuf, offset + 6
Wrap.NumPut &h68, dbuf, offset + 10, "b" // push pStm
Wrap.NumPut pStm, dbuf, offset + 11
Wrap.NumPut &hE8, dbuf, offset + 15, "b" // call CoGetInterfaceAndReleaseStream
Wrap.NumPut (AddrCoGet - (dbuf + offset + 20)), dbuf, offset + 16
Wrap.NumPut &hA1, dbuf, offset + 20, "b" // mov eax, [ppv]
Wrap.NumPut ppv, dbuf, offset + 21
Wrap.NumPut &hA3, dbuf, offset + 25, "b" // mov [params], eax
Wrap.NumPut params, dbuf, offset + 26
End Function
//{Class_Terminate
Private Sub Class_Terminate
Wrap.HeapFree hHeap, 0, res
Wrap.HeapFree hHeap, 0, swIID
Wrap.HeapFree hHeap, 0, pCLSID
Wrap.HeapFree hHeap, 0, pIID
Wrap.HeapFree hHeap, 0, ppv
Wrap.HeapFree hHeap, 0, ppOle
Wrap.HeapFree hHeap, 0, buf
Wrap.HeapFree hHeap, 0, dbuf
Wrap.HeapFree hHeap, 0, pIID_Disp
Set Ref1 = Nothing
Set Ref2 = Nothing
End Sub
//}
End Class
Set oServ = New Service
//}==========================================================
//vfunc .........Универсальная, для вызова функций интерфейса..............
Public Function vfunc(pObj, offset)
Addr = Wrap.NumGet(Wrap.NumGet(pObj), offset)
Wrap.NumPut Addr - (buf + 1 + 4), buf, 1
End Function
//IUnknown_QueryInterface
Public Function IUnknown_QueryInterface(pObj, riid, ppv1)
Wrap.StringFromGUID2 riid, swIID, 256
sIID = Wrap.StrGet(swIID)
If sIID = IID_IHTMLDocument2 Then
IUnknown_QueryInterface = E_NOINTERFACE
Wrap.NumPut 0, ppv1
Else
Wrap.NumPut oldAddr1 - (buf + 1 + 4), buf, 1
IUnknown_QueryInterface = Wrap.IUnknown_QueryInterface(pObj, riid, ppv1)
End If
End Function
//IOleObject_SetClientSite
Public Function IOleObject_SetClientSite(pObj, pClientSite)
Wrap.NumPut oldAddr2 - (buf + 1 + 4), buf, 1
IOleObject_SetClientSite = Wrap.IOleObject_SetClientSite(pObj, pClientSite)
//'=====================================================
//'Перехват IOleContainer::QueryInterface
pOleContainer = Wrap.NumGet(ppOle)
vtable = Wrap.NumGet(pOleContainer)
oldAddr1 = Wrap.NumGet(vtable, (1 - 1) * 4)
Wrap.VirtualProtect vtable, 4, PAGE_EXECUTE_READWRITE, res
Wrap.NumPut Addr1, vtable, 0
End Function
//
//Hook
Public Function Hook()
sKey = "CLSID\" & CLSID_Outlook & "\InprocServer32"
r = Wrap.RegOpenKey(HKEY_CLASSES_ROOT, sKey, ppv)
hk = Wrap.NumGet(ppv)
Wrap.NumPut 256, ppv
r = Wrap.RegQueryValue(hk, 0, swIID, ppv)
fullPath = Wrap.StrGet(swIID, "s")
//MsgBox fullPath
r = Wrap.Register(fullPath, "DllGetClassObject" , "i=ppp", "r=l")
//'=====================================================
//'Создаем фабрику-классов
Wrap.NumPut 0, ppv
Wrap.IIDFromString CLSID_Outlook, pCLSID
Wrap.IIDFromString IID_IClassFactory, pIID
q = Wrap.DllGetClassObject(pCLSID, pIID, ppv)
//'=====================================================
//'Создаем объект IViewCtl
pIClassFactory = Wrap.NumGet(ppv)
Wrap.NumPut 0, ppv
Wrap.IIDFromString IID_IViewCtl, pIID
vfunc pIClassFactory, &h0C
q = Wrap.IClassFactory_CreateInstance(pIClassFactory, 0, pIID, ppv)
//'=====================================================
//'Запрашиваем интерфейс IOleObject
pIViewCtl = Wrap.NumGet(ppv)
Wrap.NumPut 0, ppv
Wrap.IIDFromString IID_IOleObject, pIID
vfunc pIViewCtl, (1 - 1 ) * 4
q = Wrap.IUnknown_QueryInterface(pIViewCtl, pIID, ppv)
//'=====================================================
//'Перехватываем IOleObject::SetClientSite
pIOleObject = Wrap.NumGet(ppv)
vtable = Wrap.NumGet(pIOleObject)
oldAddr2 = Wrap.NumGet(vtable, (4 - 1) * 4)
Wrap.VirtualProtect vtable + &h0C, 4, PAGE_EXECUTE_READWRITE, res
Wrap.NumPut Addr3, vtable, &h0C
End Function
//DelHook
Public Function DelHook()
//'Убираем перехват на IOleObject::SetClientSite
vtable = Wrap.NumGet(pIOleObject)
Wrap.NumPut oldAddr2, vtable, &h0C
Wrap.VirtualProtect vtable + &h0C, 4, Wrap.NumGet(res), res
//'Снимаем перехват
If pOleContainer <> 0 Then
vtable = Wrap.NumGet(pOleContainer)
Wrap.NumPut oldAddr1, vtable, 0
Wrap.VirtualProtect vtable, 4, Wrap.NumGet(res), res
End If
vfunc pIClassFactory, (3 - 1) * 4
q = Wrap.IUnknown_Release(pIClassFactory)
Set oServ = Nothing
Set Wrap = Nothing
End Function
Hook()
Function Window_Onresize()
Set Obj = document.getElementById("Outlook")
Obj.width = document.body.clientWidth - 20
Obj.height = document.body.clientHeight - 20
End Function
Function Window_Onload()
//MsgBox "Window_Onload"
Window_Onresize()
End Function
Function Window_OnUnload()
//MsgBox "Window_OnUnload"
DelHook()
End Function
</script>
</head>
<body>
<object id=Outlook classid=clsid:261B8CA9-3BAF-4BD0-B0C2-BF04286785C6></object>
<script FOR=Outlook EVENT=SelectionChange language=vbscript>
Set Selection = Outlook.Selection
If Selection.Count() >0 Then
Set mes = Selection.Item(1)
MsgBox mes.EntryID
End If
</script>
</body>
</html>