ProMiNick
Joined: 24 Mar 2012
Posts: 806
Location: Russian Federation, Sochi
|
realizing COM-server in fasm
stage: sources are not finished
the main file USECOM2.0.ASM
format PE GUI 4.0 DLL
entry DllEntryPoint
include 'win32w.inc'
include 'COMINCLUDES.INC'
section '.data' data readable writeable
CMyObj:
ISPSE IShellPropSheetExt@vtbl \
<CMyObj@@QueryInterface@adjustor@4,\
CMyObj@@AddRef@adjustor@4,\
CMyObj@@Release@adjustor@4>,\
CMyObj@@AddPages,\;(int (*)(_PSP *,long),long)
CMyObj@@ReplacePage ;(uint,int (*)(_PSP *,long),long)
ISEI IShellExtInit@vtbl \
<CMyObj@@QueryInterface,\
CMyObj@@AddRef,\
CMyObj@@Release>,\
CMyObj@@Initialize ;(_ITEMIDLIST const *,IDataObject *,HKEY__ *)
CLSID_CMyObj GUID 00FF00FF-00FF-00FF-00FF-123456789ABC
vMyObjClassFactory:
IClassFactory@vtbl \
<CMyObjCF@@QueryInterface,\
CMyObjCF@@AddRef,\
CMyObjCF@@Release>,\
CMyObjCF@@CreateInstance,\;(IUnknown *,_GUID const &,void * *)
CMyObjCF@@LockServer ;(int)
IID_IUnknown GUID 00000000-0000-0000-C000-000000000046
IID_IClassFactory GUID 00000001-0000-0000-C000-000000000046
IID_IShellExtInit GUID 000214E8-0000-0000-C000-000000000046
IID_IShellPropSheetExt GUID 000214E9-0000-0000-C000-000000000046
cInstancesMyObj dd 0
pvMyObjClassFactory dd vMyObjClassFactory
section '.text' code readable executable
;#in progress
proc DllEntryPoint hinstDLL,fdwReason,lpvReserved
mov eax,TRUE
ret
endp
;#in progress
proc DllCanUnloadNow hinstDLL,fdwReason,lpvReserved
mov eax,TRUE
ret
endp
include 'MyObj.inc'
include 'MyObjClassFactory.inc'
proc CMyObj@@Constructor ; ecx=This
push esi
mov esi, ecx
xor eax, eax
mov dword [esi+ 0], ISEI
mov dword [esi+ 4], ISPSE
mov dword [esi+ 8], eax
mov dword [esi+0Ch], eax
mov dword [esi+10h], eax
stdcall CMyObj@@AddRef,esi
mov eax,esi
pop esi
ret
endp
proc CMyObj@@Destructor ; ecx=This
push esi
mov esi, ecx
mov dword [esi+ 0], ISEI
mov dword [esi+ 4], ISPSE
mov eax, [esi+0Ch]
test eax, eax
jz @F
comcall eax,IUnknown,Release
@@:
mov eax, [esi+10h]
test eax, eax
jz @F
invoke RegCloseKey,eax
mov dword [esi+10h], 0
@@:
pop esi
ret
endp
proc DllGetClassObject rclsid,riid,ppv
push esi edi
GUIDcmp [rclsid],CLSID_CMyObj
pop esi edi
mov eax, E_NO_INTERFACE
jnz @F
stdcall CMyObjCF@@QueryInterface,pvMyObjClassFactory,[riid],[ppv]
@@:
ret
endp
section '.idata' import data readable
library comctl,'COMCTL32.DLL',\
advapi,'ADVAPI32.DLL',\
kernel,'KERNEL32.DLL'
import comctl,\
CreatePropertySheetPageW, 'CreatePropertySheetPageW',\
DestroyPropertySheetPage,'DestroyPropertySheetPage'
import advapi,\
RegCloseKey ,'RegCloseKey',\
RegOpenKeyExW ,'RegOpenKeyExW'
import kernel,\
InterlockedDecrement,'InterlockedDecrement',\
InterlockedIncrement,'InterlockedIncrement'
section '.edata' export data readable
export 'USECOM2.0.DLL',\
DllCanUnloadNow,'DllCanUnloadNow',\
DllGetClassObject,'DllGetClassObject'
section '.reloc' fixups data readable discardable
macros & strucs & definitions file COMINCLUDES.INC
struc GUID def
{
match d1-d2-d3-d4-d5, def
\{
.Data1 dd 0x\#d1
.Data2 dw 0x\#d2
.Data3 dw 0x\#d3
.Data4 db 0x\#d4 shr 8,0x\#d4 and 0FFh
.Data5 db 0x\#d5 shr 40,0x\#d5 shr 32 and 0FFh,0x\#d5 shr 24 and 0FFh,0x\#d5 shr 16 and 0FFh,0x\#d5 shr 8 and 0FFh,0x\#d5 and 0FFh
\}
}
macro GUIDcmp dest,src
{
mov esi,src
mov edi,dest
mov ecx,4
repe cmpsd
}
macro setptr dest,src ; used|trashed eax
{
if src eqtype eax | src eqtype 0
if dest eqtype eax | dest eqtype 0
local ..dest
label ..dest at dest
mov [..dest],src
else
mov eax,dest
mov [eax],src
end if
else
if ~ dest eq eax
mov eax,dest
end if
push src
pop [eax]
end if
}
struct PROPSHEETPAGEW_V3
dwSize dd ?
dwFlags dd ?
hInstance dd ?
pszTemplate dd ?
pszIcon dd ?
pszTitle dd ?
pfnDlgProc dd ?
lParam dd ?
pfnCallback dd ?
pcRefParent dd ? ; PSP_V1 end here
pszHeaderTitle dd ?
pszHeaderSubTitle dd ?
hActCtx dd ?
ends
struct IUnknown@vtbl
QueryInterface dd ?
AddRef dd ?
Release dd ?
ends
struct IClassFactory@vtbl
IUnk IUnknown@vtbl
CreateInstance dd ?
LockServer dd ?
ends
struct IShellPropSheetExt@vtbl
IUnk IUnknown@vtbl
AddPages dd ?
ReplacePage dd ?
ends
struct IShellExtInit@vtbl
IUnk IUnknown@vtbl
Initialize dd ?
ends
struct IDataObject@vtbl
IUnk IUnknown@vtbl
GetData dd ?
GetDataHere dd ?
QueryGetData dd ?
GetCanonicalFormatEtc dd ?
SetData dd ?
EnumFormatEtc dd ?
DAdvise dd ?
DUnadvise dd ?
EnumDAdvise dd ?
ends
interface IUnknown,\
QueryInterface,\
AddRef,\
Release
interface IClassFactory,\
QueryInterface,\
AddRef,\
Release,\
CreateInstance,\
LockServer
interface IShellExtInit,\
QueryInterface,\
AddRef,\
Release,\
Initialize
interface IDataObject,\
QueryInterface,\
AddRef,\
Release,\
GetData,\
GetDataHere,\
QueryGetData,\
GetCanonicalFormatEtc,\
SetData,\
EnumFormatEtc,\
DAdvise,\
DUnadvise,\
EnumDAdvise
sizeof.IID = 16
E_NOTIMPL = 80004001h
E_NO_INTERFACE = 80004002h
E_FAIL = 80004005h
E_OUTOFMEMORY = 8007000Eh
ideas
;This- structure of COM-object
; in most coommon case
; with N number of slots for interface (each slot has ptr to interface)
; if one interface comletely included in other interface they share same interface slot
; with F number of additional fields
; in simplest case (for ex. ClassFactory): N=1, F=0 - whole structure is just 1 ptr
; in most complex case (for. ex. OOP interfaced object): structure is multilevel - it not contains slots for interface, but contain ptr to that slots (or ptr to ptr to)
; one rule: relization of all methods of every interface supported by pvself structure must know relativities of all members in this structure (members that used in that method)
;cInstances - dll field, increased with all AddRef & decreased with all Release of every COM-object created from interfaces realized in that DLL
;every COM-object exept ClassFactory has its own refCounter, that is affected with AddRef & Release too.
;#pseudocode QueryInterface(This,riid,ppv)
;{
; if [riid] in list of supported IID
; comcall ([This]+IndexofInterfaceSlot),IUnknown,AddRef
; setptr [ppv],[This]
; RESULT S_OK
; else
; setptr [ppv],0
; RESULT E_NO_INTERFACE
;}
;#pseudocode AddRef(This)
;{
; InterlockedIncrement(cAllInstances)
; if This is not ClassFactory (because ClassFactory has only 1 instance direct in DLL)
; InterlockedIncrement(InstanceCounter) of that This structure
;}
;#pseudocode Release(This)
;{
; InterlockedDecrement(cAllInstances)
; if This is not ClassFactory (because ClassFactory has only 1 instance direct in DLL)
; InterlockedDecrement(InstanceCounter) of that This structure
;}
MyObjClassFactory.inc
proc CMyObjCF@@QueryInterface This,riid,ppv
push ebx esi edi
xor ebx, ebx
setptr [ppv],ebx
mov ebx, [This]
GUIDcmp [riid],IID_IUnknown
jz @F
GUIDcmp [riid],IID_IClassFactory
jz @F
mov eax, E_NO_INTERFACE
jmp .locret
@@:
comcall ebx,IClassFactory,AddRef
setptr [ppv],ebx
xor eax,eax
.locret:
pop ebx esi edi
ret
endp
proc CMyObjCF@@AddRef This
invoke InterlockedIncrement,cInstancesMyObj
ret
endp
proc CMyObjCF@@Release This
invoke InterlockedDecrement,cInstancesMyObj
ret
endp
proc CMyObjCF@@CreateInstance This,pUnk,rclsid,ppv
push esi
cmp [pUnk], 0
jz @F
mov eax, E_NOTIMPL
jmp .locret
@@:
;stdcall new,14h
pop ecx
test eax,eax
jz .loc_5F0F1A24
mov ecx, eax
call CMyObj@@Constructor
test eax,eax
jz .loc_5F0F1A24
mov esi, eax
comcall esi,IShellExtInit,QueryInterface,[rclsid],[ppv]
push edi
mov edi,eax
comcall esi,IShellExtInit,Release
test edi, edi
pop edi
jge .loc_5F0F1A53
mov eax, E_NO_INTERFACE
jmp .locret
.loc_5F0F1A24:
mov eax, E_OUTOFMEMORY
jmp .locret
.loc_5F0F1A53:
xor eax, eax
.locret:
pop esi
ret
endp
proc CMyObjCF@@LockServer This,fLock
xor eax, eax
ret
endp
MyObj.inc
proc CMyObj@@QueryInterface@adjustor@4 This,riid,ppv
sub [This], 4
jmp CMyObj@@QueryInterface
endp
proc CMyObj@@AddRef@adjustor@4 This
sub [This], 4
jmp CMyObj@@AddRef
endp
proc CMyObj@@Release@adjustor@4 This,riid,ppv
sub [This], 4
jmp CMyObj@@Release
endp
;#in progress body
proc CMyObj@@AddPages This,pfnAddPage,lParam
mov eax,TRUE
ret
endp
proc CMyObj@@ReplacePage This,uPageID,pfnReplacePage,lParam
mov eax,E_NOTIMPL
ret
endp
proc CMyObj@@QueryInterface This,riid,ppv
;1st ptr to interface ([ [This]+0]) of COM-object points to both IShellExtInit & IUnknown(IUnknown is part of IShellExtInit)
;because of IShellExtInit & IShellPropSheetExt no one of them don`t include second one
;2nd ptr to interface ([ [This]+4]) of COM-object points to only IShellPropSheetExt (IUnknown is part of IShellPropSheetExt, but it already realized inside IShellExtInit)
push ebx esi edi
xor ebx, ebx
setptr [ppv],ebx
mov ebx,[This]
GUIDcmp [riid],IID_IUnknown
jz @F
GUIDcmp [riid],IID_IShellExtInit
jz @F
GUIDcmp [riid],IID_IShellPropSheetExt
jnz .loc_5F0F1ACF
lea ebx,[ebx+4] ; fix for IShellPropSheetExt because it in 2nd slot of COM-object interfaces
jmp @F
.loc_5F0F1ACF:
mov eax, E_NO_INTERFACE
jmp .locret
@@:
comcall ebx,IUnknown,AddRef
setptr [ppv],ebx
xor eax,eax
.locret:
pop ebx esi edi
ret
endp
proc CMyObj@@AddRef This
push esi
mov esi,[InterlockedIncrement]
stdcall esi,cInstancesMyObj
mov eax,[This]
add eax,8
stdcall esi,eax
pop esi
ret
endp
proc CMyObj@@Release This
push esi
mov esi,[InterlockedDecrement]
stdcall esi,cInstancesMyObj
mov eax,[This]
add eax,8
stdcall esi,eax
pop esi
ret
endp
proc CMyObj@@Initialize This,pidlFolder,pDO,hkeyProgID
push esi
mov esi,[This]
mov ecx,esi
call CMyObj@@Destructor
mov eax, [pDO]
mov [esi+0Ch], eax
test eax, eax
jz @F
comcall eax,IUnknown,AddRef ;eax,IDataObject,AddRef
@@:
cmp [hkeyProgID],0
jz @F
add esi,10
invoke RegOpenKeyExW,[hkeyProgID],0,0,2000000h,esi
@@:
xor eax, eax
pop esi
ret
endp
i expect some critics if i do some things wrong
in the end i will post here complete & working src (hopely with your suggestions) - but i need time
_________________ I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.
Last edited by ProMiNick on 04 Apr 2017, 18:53; edited 3 times in total
|