汇编语言接口开发库(这个库支持多重接口的继承) By 皇霸(于2009-4-14发表)

ifndef __ComUtils_Inc
    __ComUtils_Inc        equ        1
.nolist
    include SysUtils.inc
    include ole32.inc
    include oleaut32.inc
    include advapi32.inc
    
    includelib ole32.lib
    includelib oleaut32.lib
    includelib advapi32.lib
.listall

;接口信息偏移量
vmtComRtti        equ        -8
vmtInited        equ        -4
vmtIUnknown        equ        8
;类虚拟方法表偏移量
vmtAfterNew        equ        0
vmtBeforeFree    equ        4

@LPMethod LPQueryInterface,:DWORD,:DWORD,:DWORD
@LPMethod LPAddRef,:DWORD
@LPMethod LPRelease,:DWORD

ComRtti struct    ;接口运行期信息
    lpParent    DWORD        NULL            ;父接口GuidRtti地址
    szName        BYTE        36    dup(0)        ;接口名
    dwSize        DWORD        0                ;接口大小
    lpGuid        DWORD        NULL            ;接口GUID指针
ComRtti ends

ClassRtti struct    ;类运行期信息
    szName    BYTE    36    dup(0)    ;类名
    dwSize    DWORD    0            ;类大小
    nImpCOM    DWORD    0            ;实现的接口数目
    lpGuid    DWORD    NULL        ;类Guid指针
ClassRtti ends

KernelRtti struct    ;用于支持多重接口的核心信息
    lpObjectAddress        DWORD    NULL    ;实例对象基地址
    nRefCountOffset        DWORD    0        ;引用计数偏移量
    nClassRttiOffset    DWORD    0        ;类运行期信息偏移量
    nClassVmtOffset        DWORD    0        ;类虚拟方法表偏移量
KernelRtti ends

szIID_IUnknown    textequ        <{000000000H,00000H,00000H,{0C0H,000H,000H,000H,000H,000H,000H,046H}}>
IUnknown struct    ;所有接口的基接口
    QueryInterface    LPQueryInterface    NULL
    AddRef            LPAddRef            NULL
    Release            LPRelease            NULL
IUnknown ends

IUnknownEx struct    ;扩展接口类型
    lpRtti        DWORD        offset        IUnknown_Rtti    ;指向接口及其父接口GUID链
    dwUnused    DWORD        FALSE
                IUnknown    <>
IUnknownEx ends

;接口定义:ComName:接口名  IBase:父接口
@IComDef macro ComName:req,ComBase:=<IUnknown>
    $ComName        textequ        <ComName>
    $ComBase        textequ        <ComBase>
    $ComDesc        textequ        @CatStr(<!">,<ComName>,<!">)
    $ComNameEx        textequ        @CatStr(<ComName>,<Ex>)
    $ComBaseRtti    textequ        @CatStr(<ComBase>,<_Rtti>)
    $ComNameRtti    textequ        @CatStr(<ComName>,<_Rtti>)
    $GuidText        textequ        @CatStr(<szIID_>,<ComName>)
    $Guid            textequ        @CatStr(<IID_>,<ComName>)
endm

@Guid macro szGuidText:req
    $GuidText    textequ        <szGuidText>
    .const
        $Guid            GUID        $GuidText
        $ComNameRtti    ComRtti        <offset $ComBaseRtti,$ComDesc,sizeof $ComName,offset $Guid>
    $ComName struct
        $ComBase    <>
endm

__GuidEx macro szGuid:req
    $szGuidText    textequ    @CatStr(<{0>,@SubStr(<szGuid>,2,8),<H,0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,11,4),<H,0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,16,4),<H,{0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,21,2),<H,0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,23,2),<H,0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,26,2),<H,0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,28,2),<H,0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,30,2),<H,0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,32,2),<H,0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,34,2),<H,0>)
    $szGuidText    textequ    @CatStr(<%$szGuidText>,@SubStr(<szGuid>,36,2),<H}}>)
endm

@GuidEx macro GuidText:req
    __GuidEx GuidText
    @Guid $szGuidText
endm


;定义接口方法  MethodName:接口方法名  argList:方法参数
@IMethod macro MethodName:req,argList:VARARG
local    @MethodProto,@MethodPtr
    ifb<argList>
        @MethodProto    typedef        proto:DWORD
    else
        @MethodProto    typedef        proto:DWORD,argList
    endif
    @MethodPtr        typedef            ptr     @MethodProto
    MethodName        @MethodPtr        NULL
endm

;接口定义结束
@IComEnd macro
    $ComName ends
    
    $ComNameEx struct
        lpRtti        DWORD        NULL
        dwUnused    DWORD        FALSE
                    $ComName    <>
    $ComNameEx ends
endm


@CoClassDef macro ClassName:req,argList:VARARG    ;多重接口实现类定义开始
    $ClassName        textequ        <ClassName>
    $argList        textequ        <argList>
    $ClassDesc        textequ        @CatStr(<!">,<ClassName>,<!">)
    $ClassGuid        textequ        @CatStr(<CLSID_>,<ClassName>)            ;类Guid
    $DataSec        textequ        @CatStr(<ClassName>,<_DataSection>)        ;数据定义区
    $ClassRtti        textequ        @CatStr(<ClassName>,<_ClassRtti>)        ;类运行期信息
    $InitVMT        textequ        @CatStr(<ClassName>,<_InitVMT>)            ;类初始化函数
    $ClassVmtInfo    textequ        @CatStr(<ClassName>,<_ClassVmtInfo>)    ;类虚拟方法表结构
    $ClassVmt        textequ        @CatStr(<ClassName>,<_ClassVmt>)        ;类虚拟方法表
    $KernelRtti        textequ        @CatStr(<ClassName>,<_KernelRtti>)        ;核心信息
    
    $ComCount=0
    for comName,<argList>
        $ComCount=$ComCount+1
    endm
endm

@CoGuid macro szClassGuid        ;类Guid定义宏
    $szClassGuid    textequ        <szClassGuid>
    .const
        $ClassGuid    GUID        $szClassGuid
        $ClassRtti    ClassRtti    <$ClassDesc,sizeof $ClassName,$ComCount,offset $ClassGuid>
endm

@CoGuidEx macro szClassGuid
    __GuidEx szClassGuid
    @CoGuid $szGuidText
endm

@CoDataStart macro        ;多重接口实现类数据区定义开始
    $DataSec struct
        nRefCount        DWORD    1                    ;引用计数
        lpClassRtti        DWORD    offset    $ClassRtti    ;类运行期信息
endm

@CoDataEnd macro        ;多重接口实现类数据区定义结束
    $DataSec ends
endm

@CoClassEnd macro        ;多重接口实现类定义结束
    %ifndef $DataSec
        $DataSec struct
            nRefCount        DWORD    1                    ;引用计数
            lpClassRtti        DWORD    offset    $ClassRtti    ;类运行期信息
        $DataSec ends
    endif
    %ifndef $ClassVmtInfo
        $ClassVmtInfo struct
            @CoMethod AfterNew,NULL        ;对象创建后执行
            @CoMethod BeforeFree,NULL    ;对象析构前执行
            @CoMethod GetCoClassGuid,CoClass_GetCoClassGuid,:ptr GUID
            @CoMethod GetCoClassName,CoClass_GetCoClassName,:LPSTR
            @CoMethod GetCoClassSize,CoClass_GetCoClassSize,:ptr DWORD
        $ClassVmtInfo ends
    endif
    $ClassName struct
        %for comName,<$argList>
            $ComVMT    textequ    @CatStr(<%$ClassName>,<comName>,<_VMT>)
            $vptr    textequ    @CatStr(<comName>,<_vptr>)
            
            $vptr    DWORD    offset    $ComVMT + vmtIUnknown    ;相应接口的虚拟方法表指针
                    DWORD    offset    $KernelRtti                ;KernelRtti对象指针
        endm
        lpClassVMT    DWORD    offset    $ClassVmt    ;类虚拟方法表指针
        $DataSec    <1,offset $ClassRtti>
    $ClassName ends
    .data
        $KernelRtti        KernelRtti        <>    ;核心信息表
        $ClassVmt        $ClassVmtInfo    <>    ;类虚拟方法表
endm

@ComObjectAddr macro lpComObject:req    ;获取多重接口基地址
    mov        eax,lpComObject
    add        eax,4
    mov        eax,DWORD ptr[eax]    ;获取核心信息表指针
    mov        eax,(KernelRtti ptr[eax]).lpObjectAddress
    exitm<eax>
endm

@ImplementStart macro QueryInterfaceDef:=<TRUE>,AddRefDef:=<TRUE>,ReleaseDef:=<TRUE>    ;多重接口函数实现开始
.data
    %for comName,<$argList>
        $ComVMT        textequ        @CatStr(<%$ClassName>,<comName>,<_VMT>)
        $ComRtti    textequ        @CatStr(<comName>,<_Rtti>)
        $ComVmtEx    textequ        @CatStr(<comName>,<Ex>)
        $ComVMT        $ComVmtEx    <offset $ComRtti,FALSE>
    endm
.code
    $QueryInterface    textequ        @CatStr(<%$ClassName>,<_QueryInterface>)
    $AddRef            textequ        @CatStr(<%$ClassName>,<_AddRef>)
    $Release        textequ        @CatStr(<%$ClassName>,<_Release>)
    
    $AddRef proc Self:DWORD
        mov        eax,@ComObjectAddr(Self)
        inc        ($ClassName ptr[eax]).nRefCount
        mov        eax,($ClassName ptr[eax]).nRefCount
        ret
    $AddRef endp
    
    $Release proc uses edi Self:DWORD
        mov        edi,@ComObjectAddr(Self)
        dec        ($ClassName ptr[edi]).nRefCount
        mov        eax,($ClassName ptr[edi]).nRefCount
        .if eax==0
            mov        eax,($ClassName ptr[edi]).lpClassVMT
            add        eax,vmtBeforeFree
            .if DWORD ptr[eax]!=NULL
                push    edi
                call    DWORD ptr[eax]
            .endif
            @CoReleaseObject edi
            xor        eax,eax
        .endif
        ret
    $Release endp
    
    $QueryInterface proc uses edi esi Self:DWORD,lpIID:ptr IID,lpResult:ptr LPVOID
    local @dwCount:DWORD
        mov        edi,Self
        mov        esi,DWORD ptr[edi]
        add        esi,vmtComRtti
        mov        esi,DWORD ptr[esi]
        .while    esi!=NULL
            invoke    IsEqualGUID,lpIID,(ComRtti ptr[esi]).lpGuid
            .if eax
                jmp        @f
            .endif
            mov        esi,(ComRtti ptr[esi]).lpParent
        .endw
        mov        eax,$ClassRtti.nImpCOM
        mov        @dwCount,eax
        mov        edi,@ComObjectAddr(Self)
        .while @dwCount>0
            .if edi!=Self
                mov        esi,DWORD ptr[edi]
                add        esi,vmtComRtti
                mov        esi,DWORD ptr[esi]
                .while    esi!=NULL
                    invoke    IsEqualGUID,lpIID,(ComRtti ptr[esi]).lpGuid
                    .break .if eax
                    mov        esi,(ComRtti ptr[esi]).lpParent
                .endw
                .break .if eax
            .endif
            add        edi,8
            dec        @dwCount
        .endw
    @@:
        mov        esi,lpResult
        .if eax
            mov        DWORD ptr[esi],edi
            invoke    $AddRef,edi
            mov        eax,S_OK
        .else
            mov        DWORD ptr[esi],NULL
            mov        eax,E_NOINTERFACE
        .endif
        ret
    $QueryInterface endp
    
    $InitVMT proc Self:DWORD
        pushad
        mov        eax,Self
        lea        ecx,($ClassName ptr[eax]).lpClassRtti
        sub        ecx,Self
        mov        edi,eax
        add        edi,4
        %for comName,<$argList>    ;初始化接口基地址
            mov        edx,DWORD ptr[edi]    ;获取核心信息表指针
            mov        (KernelRtti ptr[edx]).lpObjectAddress,eax
            mov        (KernelRtti ptr[edx]).nClassRttiOffset,ecx
            mov        (KernelRtti ptr[edx]).nRefCountOffset,ecx
            sub        (KernelRtti ptr[edx]).nRefCountOffset,4
            mov        (KernelRtti ptr[edx]).nClassVmtOffset,ecx
            sub        (KernelRtti ptr[edx]).nClassVmtOffset,8
            
            add        edi,8
            add        esi,8
        endm
        %for comName,<$argList>
            $ComVMT        textequ        @CatStr(<%$ClassName>,<comName>,<_VMT>)
            if QueryInterfaceDef
                mov        $ComVMT.QueryInterface,$QueryInterface
            endif
            if AddRefDef
                mov        $ComVMT.AddRef,$AddRef
            endif
            if ReleaseDef
                mov        $ComVMT.Release,$Release
            endif
        endm
endm

@AfterNew macro MethodAddress ;构造函数,此宏位于 @ComMultMethodStart .. @ComMultMethodEnd段
    mov        eax,Self
    mov        eax,($ClassName ptr[eax]).lpClassVMT
    add        eax,vmtAfterNew
    mov        DWORD ptr[eax],MethodAddress
endm

@BeforeFree macro MethodAddress ;析构函数,此宏位于 @ComMultMethodStart .. @ComMultMethodEnd段
    mov        eax,Self
    mov        eax,($ClassName ptr[eax]).lpClassVMT
    add        eax,vmtBeforeFree
    mov        DWORD ptr[eax],MethodAddress
endm

@Implement macro InterName:req,InterMethod:req,ImpProc:req    ;多重接口具体实现函数
local @vmtName
    @vmtName    textequ    @CatStr(<%$ClassName>,<InterName>,<_VMT>,<.>,<InterMethod>)
        mov    @vmtName,ImpProc
endm

@ImplementEnd macro    ;多重接口函数实现结束
        mov        edi,Self
        mov        edi,($ClassName ptr[edi]).lpClassVMT
        add        edi,vmtAfterNew
        .if DWORD ptr[edi]!=NULL
            push    Self
            call    DWORD ptr[edi]
        .endif
        popad
        ret
    $InitVMT endp
endm


@CoMethodStart macro ;多重接口类自身函数定义开始
    $ClassVmtInfo struct
        @CoMethod AfterNew,NULL        ;对象创建后执行
        @CoMethod BeforeFree,NULL    ;对象析构前执行
        @CoMethod GetCoClassGuid,CoClass_GetCoClassGuid,:ptr GUID
        @CoMethod GetCoClassName,CoClass_GetCoClassName,:LPSTR
        @CoMethod GetCoClassSize,CoClass_GetCoClassSize,:ptr DWORD
endm

@CoMethod macro MethodName:req,MethodProc:req,Params:VARARG
local    @MethodProto,@MethodPtr
    ifb<Params>
        @MethodProto    typedef        proto:DWORD
    else
        @MethodProto    typedef        proto:DWORD,Params
    endif
        @MethodPtr        typedef            ptr     @MethodProto
        MethodName        @MethodPtr        MethodProc
endm

@CoMethodEnd macro ;多重接口类自身函数的具体实现
    $ClassVmtInfo ends
endm

@CoCreateObject macro ComMultObject:req    ;创建多重接口
local @ObjectCS
    @ObjectCS    textequ        @CatStr(<ComMultObject>,<_ConstEx>)
    $InitVMT    textequ        @CatStr(<ComMultObject>,<_InitVMT>)
    %ifndef @ObjectCS
        .const
            @ObjectCS    ComMultObject    <>
        .code
    endif
    pushad
    invoke    CoTaskMemAlloc,sizeof ComMultObject
    mov        IComPTR,eax
    .if eax
        invoke    MemCopy,offset @ObjectCS,IComPTR,sizeof ComMultObject
        invoke    $InitVMT,IComPTR
    .endif
    popad
    mov        eax,IComPTR
    exitm<eax>
endm

@CoReleaseObject macro lpObject:req    ;释放接口对象  IPObject:接口对象指针
    invoke    CoTaskMemFree,lpObject
endm

;调用方法接口:IMethod:接口方法名  Params:接口方法参数
@ICall macro IMethod:req,Params:VARARG
local @InterfaceID,@ObjectPtr,@IMethodID
    @ObjectPtr        textequ        @SubStr(<IMethod>,@InStr(1,<IMethod>,<[>)+1,3)  ;虚拟方法表指针
    @InterfaceID    textequ        @SubStr(<IMethod>,2,@InStr(1,<IMethod>,<! >)-1)
    @IMethodID        textequ        @SubStr(<IMethod>,@InStr(1,<IMethod>,<.>)+1)
    push    edx
    mov        edx,@ObjectPtr
    mov        IComPTR,edx
    mov        edx,DWORD ptr[edx]
    ifb<Params>
        invoke    (@InterfaceID ptr[edx]).@IMethodID,IComPTR
    else
        invoke    (@InterfaceID ptr[edx]).@IMethodID,IComPTR,Params
    endif
    pop        edx
endm

@CoCall macro CoMethod:req,Params:VARARG
local @CoClass,@CoVMT,@ObjectPtr,@CoMethodID
    @ObjectPtr        textequ        @SubStr(<CoMethod>,@InStr(1,<CoMethod>,<[>)+1,3)  ;虚拟方法表指针
    @CoClass        textequ        @SubStr(<CoMethod>,2,@InStr(1,<CoMethod>,<! >)-2)
    @CoVMT            textequ        @CatStr(<%@CoClass>,<_ClassVmtInfo>)
    @CoMethodID        textequ        @SubStr(<CoMethod>,@InStr(1,<CoMethod>,<.>)+1)
    push    edx
    mov        edx,@ComObjectAddr(@ObjectPtr)
    mov        IComPTR,edx
    mov        edx,(@CoClass ptr[edx]).lpClassVMT
    ifb<Params>
        invoke    (@CoVMT ptr[edx]).@CoMethodID,IComPTR
    else
        invoke    (@CoVMT ptr[edx]).@CoMethodID,IComPTR,Params
    endif
    pop        edx
endm


__uuidof macro IInterface:req,IDType:=<IID>
    ifidn <IDType>,<IID>
        mov        GuidPTR,offset @CatStr(<IID_>,<IInterface>)
    elseifidn <IDType>,<CLSID>
        mov        GuidPTR,offset @CatStr(<CLSID_>,<IInterface>)
    else
        mov        GuidPTR,NULL
    endif
    exitm<GuidPTR>
endm

@AllocBSTR macro szTextA:req
    mov        ComStrPTR,@WStrAlloc(szTextA)
    invoke    SysAllocString,ComStrPTR
    push    eax
    invoke    GlobalFree,ComStrPTR
    pop        eax
    exitm<eax>
endm

@FreeBSTR macro lpString:req
    invoke    SysFreeString,lpString
    mov        lpString,NULL
endm

BSTR            typedef        LPVOID
LPBSTR            typedef        ptr BSTR
HRESULT            typedef        DWORD
VARIANT_BOOL    typedef        WORD

VARIANT struct ;DWORD
    vt            WORD    VT_EMPTY    ;vtMissing
    wReserved1    WORD    0
    wReserved2    WORD    0
    wReserved3    WORD    0
    union
        lVal        SDWORD            ?   ; VT_I4
        bVal        WORD            ?   ; VT_UI1
        iVal        SWORD            ?   ; VT_I2
        fltVal        REAL4            ?   ; VT_R4
        dblVal        REAL8            ?   ; VT_R8
        boolVal        VARIANT_BOOL    ?   ; VT_BOOL
        scode        DWORD            ?   ; VT_ERROR
        cyVal        QWORD            ?   ; VT_CY
        date        QWORD            ?   ; VT_DATE
        bstrVal        LPBSTR            ?   ; VT_BSTR
        punkVal        LPVOID            ?   ; VT_UNKNOWN
        pdispVal    LPVOID            ?   ; VT_DISPATCH
        parray        LPVOID            ?   ; VT_ARRAY
        pbVal        LPVOID            ?   ; VT_BYREF|VT_UI1
        piVal        LPVOID            ?   ; VT_BYREF|VT_I2
        plVal        LPVOID            ?   ; VT_BYREF|VT_I4
        pfltVal        LPVOID            ?   ; VT_BYREF|VT_R4
        pdblVal        LPVOID            ?   ; VT_BYREF|VT_R8
        pboolVal    LPVOID            ?   ; VT_BYREF|VT_BOOL
        pscode        LPVOID            ?   ; VT_BYREF|VT_ERROR
        pcyVal        LPVOID            ?   ; VT_BYREF|VT_CY
        pdate        LPVOID            ?   ; VT_BYREF|VT_DATE
        pbstrVal    LPVOID            ?   ; VT_BYREF|VT_BSTR
        ppunkVal    LPVOID            ?   ; VT_BYREF|VT_UNKNOWN
        ppdispVal    LPVOID            ?   ; VT_BYREF|VT_DISPATCH
        pparray        LPVOID            ?   ; VT_BYREF|VT_ARRAY
        pvarVal        LPVOID            ?   ; VT_BYREF|VT_VARIANT
        byref        LPVOID            ?   ; Generic ByRef
        cVal        SBYTE            ?   ; VT_I1
        uiVal        WORD            ?   ; VT_UI2
        ulVal        DWORD            ?   ; VT_UI4
        intVal        SWORD            ?   ; VT_INT
        uintVal        WORD            ?   ; VT_UINT
        pdecVal        LPVOID            ?   ; VT_BYREF|VT_DECIMAL
        pcVal        LPVOID            ?   ; VT_BYREF|VT_I1
        puiVal        LPVOID            ?   ; VT_BYREF|VT_UI2
        pulVal        LPVOID            ?   ; VT_BYREF|VT_UI4
        pintVal        LPVOID            ?   ; VT_BYREF|VT_int
        puintVal    LPVOID            ?   ; VT_BYREF|VT_uint
    ends
VARIANT ends

CONNECTDATA struct
    pUnk        DWORD    NULL    ;ptr IUnknown
    dwCookie    DWORD    0
CONNECTDATA ends

LICINFO struct
    cbLicInfo            DWORD    0
    fRuntimeKeyAvail    DWORD    FALSE
    fLicVerified        DWORD    FALSE
LICINFO ends

@IComDef IDispatch,IUnknown
@Guid <{000020400H,00000H,00000H,{0C0H,000H,000H,000H,000H,000H,000H,046H}}>
    @IMethod GetTypeInfoCount,:DWORD
    @IMethod GetTypeInfo,:DWORD,:DWORD,:DWORD
    @IMethod GetIDsOfNames,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
    @IMethod InvokeA,:DWORD,:DWORD,:DWORD,:WORD,:DWORD,:DWORD,:DWORD,:DWORD
@IComEnd

@IComDef IClassFactory,IUnknown ;类厂
@Guid <{000000001H,00000H,00000H,{0C0H,000H,000H,000H,000H,000H,000H,046H}}>
    @IMethod    CreateInstance,:DWORD,:DWORD,:DWORD
    @IMethod    LockServer,:DWORD
@IComEnd

@IComDef IClassFactory2,IClassFactory
@GuidEx <"B196B28F-BAB4-101A-B69C-00AA00341D07">
    @IMethod GetLicInfo,:ptr LICINFO
    @IMethod RequestLicKey,:DWORD,:ptr BSTR
    @IMethod CreateInstanceLic,:ptr IUnknown,:ptr IUnknown,:ptr GUID,:BSTR,:ptr ptr DWORD
@IComEnd

@IComDef IShellLinkA,IUnknown
@Guid <{0000214EEH,00000H,00000H,{0C0H,000H,000H,000H,000H,000H,000H,046H}}>
    @IMethod GetPathA,:DWORD,:DWORD,:DWORD,:DWORD
    @IMethod GetIDListA,:DWORD
    @IMethod SetIDListA,:DWORD
    @IMethod GetDescriptionA,:DWORD,:DWORD
    @IMethod SetDescriptionA,:DWORD
    @IMethod GetWorkingDirectoryA,:DWORD,:DWORD
    @IMethod SetWorkingDirectoryA,:DWORD
    @IMethod GetArgumentsA,:DWORD,:DWORD
    @IMethod SetArgumentsA,:DWORD
    @IMethod GetHotKeyA,:DWORD
    @IMethod SetHotkeyA,:WORD
    @IMethod GetShowCmdA,:DWORD
    @IMethod SetShowCmdA,:DWORD
    @IMethod GetIconLocationA,:DWORD,:DWORD,:DWORD
    @IMethod SetIconLocationA,:DWORD,:DWORD
    @IMethod SetRelativePathA,:DWORD,:DWORD
    @IMethod ResolveA,:DWORD,:DWORD
    @IMethod SetPathA,:DWORD
@IComEnd

@IComDef IPersistFile,IUnknown
@Guid <{0000010BH,00000H,00000H,{0C0H,000H,000H,000H,000H,000H,000H,46H}}>
    @IMethod GetClassID,:DWORD
    @IMethod IsDirty
    @IMethod Load,:DWORD,:DWORD
    @IMethod Save,:DWORD,:DWORD
    @IMethod SaveCompleted,:DWORD
    @IMethod GetCurFile,:DWORD
@IComEnd

@IComDef IEnumConnections,IUnknown
@GuidEx <"B196B287-BAB4-101A-B69C-00AA00341D07">
    @IMethod Next,:DWORD,:ptr CONNECTDATA,:ptr DWORD
    @IMethod Skip,:DWORD
    @IMethod Reset
    @IMethod Clone,:ptr ptr IEnumConnections
@IComEnd

@IComDef IConnectionPoint,IUnknown
@GuidEx <"B196B286-BAB4-101A-B69C-00AA00341D07">
    @IMethod GetConnectionInterface,:ptr GUID
    @IMethod GetConnectionPointContainer,:ptr ptr IConnectionPointContainer
    @IMethod Advise,:ptr IUnknown,:ptr DWORD
    @IMethod Unadvise,:DWORD
    @IMethod EnumConnections,:ptr ptr IEnumConnections
@IComEnd

@IComDef IEnumConnectionPoints,IUnknown
@GuidEx <"B196B285-BAB4-101A-B69C-00AA00341D07">
    @IMethod Next,:DWORD,:ptr IConnectionPoint,:ptr DWORD
    @IMethod Skip,:DWORD
    @IMethod Reset
    @IMethod Clone,:ptr ptr IEnumConnectionPoints
@IComEnd

@IComDef IConnectionPointContainer,IUnknown
@GuidEx <"B196B284-BAB4-101A-B69C-00AA00341D07">
    @IMethod EnumConnectionPoints,:ptr ptr IEnumConnectionPoints
    @IMethod FindConnectionPoint,:ptr GUID,:ptr ptr IConnectionPoint
@IComEnd
.const
    vtMissing    VARIANT    <VT_ERROR,,,,<-2147352572>>
.const
    IID_IUnknown        GUID        szIID_IUnknown
    CLSID_ShellLinkA    GUID        {000021401H,00000H,00000H,{0C0H,000H,000H,000H,000H,000H,000H,046H}}
    IUnknown_Rtti        ComRtti        <NULL,"IUnknown",sizeof IUnknown,offset IID_IUnknown>
.data
    IComPTR                DWORD        NULL
    GuidPTR                DWORD        NULL
    ComStrPTR            DWORD        NULL
.code
CoClass_GetCoClassGuid proc Self:DWORD,lpResult:ptr GUID
    pushad
    mov        edi,Self
    add        edi,4
    mov        edi,DWORD ptr[edi]    ;获取核心信息表指针
    mov        ecx,(KernelRtti ptr[edi]).nClassRttiOffset
    mov        edi,@ComObjectAddr(Self)
    add        edi,ecx
    mov        edi,DWORD ptr[edi]
    invoke    MemCopy,(ClassRtti ptr[edi]).lpGuid,lpResult,sizeof GUID
    popad
    ret
CoClass_GetCoClassGuid endp

CoClass_GetCoClassName proc Self:DWORD,lpResult:LPSTR
    pushad
    mov        edi,Self
    add        edi,4
    mov        edi,DWORD ptr[edi]    ;获取核心信息表指针
    mov        ecx,(KernelRtti ptr[edi]).nClassRttiOffset
    mov        edi,@ComObjectAddr(Self)
    add        edi,ecx
    mov        edi,DWORD ptr[edi]
    invoke    lstrcpyA,lpResult,addr (ClassRtti ptr[edi]).szName
    popad
    ret
CoClass_GetCoClassName endp

CoClass_GetCoClassSize proc Self:DWORD,lpResult:ptr DWORD
    pushad
    mov        edi,Self
    add        edi,4
    mov        edi,DWORD ptr[edi]    ;获取核心信息表指针
    mov        ecx,(KernelRtti ptr[edi]).nClassRttiOffset
    mov        edi,@ComObjectAddr(Self)
    add        edi,ecx
    mov        edi,DWORD ptr[edi]
    mov        ecx,(ClassRtti ptr[edi]).dwSize
    mov        eax,lpResult
    mov        DWORD ptr[eax],ecx
    popad
    ret
CoClass_GetCoClassSize endp

GuidToStringDef proc stGuid:GUID,lpResult:LPSTR
    jmp        @Cvt
@FmtText:
    db        "{0%08XH,0%04XH,0%04XH,{0%02XH,0%02XH,0%02XH,0%02XH,0%02XH,0%02XH,0%02XH,0%02XH}}",NULL
@Cvt:
    $Index=8
    while $Index
        $Index=$Index-1
        movzx    eax,stGuid.Data4[$Index]
        push    eax
    endm
    movzx    eax,stGuid.Data3
    push    eax
    movzx    eax,stGuid.Data2
    push    eax
    push    stGuid.Data1
    lea        eax,@FmtText
    push    eax
    push    lpResult
    call    wsprintf
    ret
GuidToStringDef endp

DllRegisterServerEx proc hDll:DWORD,lpClsid:ptr GUID,lpszSampleProgID:LPCSTR,\
    lpszProgID:LPCSTR,lpszDesc:LPCSTR,lpszThreadType:LPCSTR
local @hKey:DWORD
local @hKey2:DWORD
local @hKey3:DWORD
local @szBufferA[MAX_PATH]:BYTE
local @szBufferW[MAX_PATH]:WORD
local @lpTypeInfo:DWORD
    pushad
    jmp        @Start
@szCLSID:
    db        "CLSID",NULL
@szInprocServer32:
    db        "InprocServer32",NULL
@szThreadModel:
    db        "ThreadingModel",NULL
@Start:
    invoke    RegCreateKey,HKEY_CLASSES_ROOT,lpszSampleProgID,addr @hKey
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    lstrlen,lpszDesc
    invoke    RegSetValue,@hKey,NULL,REG_SZ,lpszDesc,eax
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    RegCreateKey,@hKey,addr @szCLSID,addr @hKey2
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    StringFromGUID2,lpClsid,addr @szBufferW,MAX_PATH
    invoke    WtoA,addr @szBufferW,addr @szBufferA,MAX_PATH
    invoke    lstrlen,addr @szBufferA
    invoke    RegSetValue,@hKey2,NULL,REG_SZ,addr @szBufferA,eax
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    RegCloseKey,@hKey
    invoke    RegCloseKey,@hKey2
    invoke    RegCreateKey,HKEY_CLASSES_ROOT,addr @szCLSID,addr @hKey
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    RegCreateKey,@hKey,addr @szBufferA,addr @hKey2
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    lstrlen,lpszDesc
    invoke    RegSetValue,@hKey2,NULL,REG_SZ,lpszDesc,eax
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    GetModuleFileName,hDll,addr @szBufferA,MAX_PATH
    .if eax==0
        inc        eax
        jmp        @f
    .endif
    invoke    RegCreateKey,@hKey2,addr @szInprocServer32,addr @hKey3
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    RegSetValue,@hKey3,NULL,REG_SZ,addr @szBufferA,MAX_PATH
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    lstrlen,lpszThreadType
    invoke    RegSetValueEx,@hKey3,addr @szThreadModel,0,REG_SZ,lpszThreadType,eax
    .IF eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    RegCloseKey,@hKey3
    invoke    RegCreateKey,@hKey2,lpszProgID,addr @hKey3
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    lstrlen,lpszSampleProgID
    invoke    RegSetValue,@hKey3,NULL,REG_SZ,lpszSampleProgID, eax
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    RegCloseKey,@hKey3
    .if @hKey!=NULL
        invoke    RegCloseKey,@hKey
    .endif
    .if @hKey2!=NULL
        invoke    RegCloseKey,@hKey2
    .endif
    .if @hKey3!=NULL
        invoke    RegCloseKey,@hKey3
    .endif
    invoke    AtoW,addr @szBufferA,addr @szBufferW,MAX_PATH
    .if !eax
        mov        eax,S_FALSE
        jmp        @f
    .endif
    invoke    LoadTypeLib,addr @szBufferW,addr @lpTypeInfo    ;@szBufferW==ModuleFileName
    .if eax!=ERROR_SUCCESS
        mov        eax,S_FALSE
        jmp        @f
    .endif
    invoke    RegisterTypeLib,@lpTypeInfo,addr @szBufferW,NULL
    .if eax!=ERROR_SUCCESS
        mov        eax,S_FALSE
        jmp        @f
    .else
        mov        edi,@lpTypeInfo
        @ICall    (IUnknown ptr[edi]).Release
    .endif
    xor        eax,eax
@@:
    mov        @hKey,eax
    popad
    mov        eax,@hKey
    ret
DllRegisterServerEx endp

GuardedDeleteKey PROC hKey:DWORD,lpszSubKey:LPCSTR
local @szSubKeyName[MAX_PATH+1]:BYTE
local @hSubkey:DWORD
    pushad
    invoke    RegOpenKey,hKey,lpszSubKey,addr @hSubkey
    .if eax!=ERROR_SUCCESS
        mov        eax,REGDB_E_INVALIDVALUE
        jmp        @f
    .endif
    .while TRUE
        invoke    RegEnumKey,@hSubkey,0,addr @szSubKeyName,MAX_PATH+1
        .break .if eax==ERROR_NO_MORE_ITEMS
        invoke    GuardedDeleteKey,@hSubkey,addr @szSubKeyName
    .endw
    invoke    RegCloseKey,@hSubkey
    invoke    RegDeleteKey,hKey,lpszSubKey
    mov        @hSubkey,eax
@@:
    popad
    mov        eax,@hSubkey
    ret
GuardedDeleteKey endp

DllUnregisterServerEx proc lpClsid:ptr GUID,lpszSampleProgID:LPCSTR
local @hSubkey:DWORD
local @szBufferA[MAX_PATH]:BYTE
local @szBufferW[MAX_PATH]:WORD
    pushad
    jmp        @Start
@szCLSID:
    db        "CLSID",NULL
@Start:
    invoke    StringFromGUID2,lpClsid,addr @szBufferW,MAX_PATH
    invoke    WtoA,addr @szBufferW,addr @szBufferA,MAX_PATH
    invoke    GuardedDeleteKey,HKEY_CLASSES_ROOT,lpszSampleProgID
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    RegOpenKey,HKEY_CLASSES_ROOT,addr @szCLSID,addr @hSubkey
    invoke    GuardedDeleteKey,@hSubkey,addr @szBufferA
    .if eax!=ERROR_SUCCESS
        jmp        @f
    .endif
    invoke    RegCloseKey,@hSubkey
@@:
    popad
    xor        eax,eax
    ret
DllUnregisterServerEx endp

endif

并不是所有的贴子都是原创,此时作者均指发表的人而不是文章的作者,作者会说明是否是转贴