; AsmCtrl.ocx        copyright 7/24/00 Ernest J Murphy
.NOLIST  ; keep the list file small, don't add the std libs to it.
.386
.model flat, stdcall
option casemap:none ; case sensitive

;--------------------------------------------------------------------------

;DEBUGL  EQU 1

;--------------------------------------------------------------------------
include     \masm32\include\windows.inc
include     \masm32\include\user32.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\advapi32.inc    
include     \masm32\include\oleaut32.inc
include     \masm32\include\masm32.inc
include     \masm32\include\ole32.inc
include     \masm32\include\gdi32.inc


include     \masm32\com\include\oaidl.inc
include     \masm32\com\include\L.inc
include     \masm32\com\include\language.inc
include     \masm32\com\include\colib.inc
include     \masm32\com\include\olectl.inc
include     \masm32\com\include\component.inc

include     IAsmCtrl.inc
include     AsmCtrl_vtable.inc

includelib  \masm32\lib\user32.lib
includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\advapi32.lib
includelib  \masm32\lib\oleaut32.lib
includelib  \masm32\lib\ole32.lib
includelib  \masm32\lib\masm32.lib
includelib  \masm32\lib\gdi32.lib
includelib  \masm32\COM\colib\colib.lib

PUBLIC      ClassMap

;--------------------------------------------------------------------------
.LISTALL ; NOW let's list everything

;--------------------------------------------------------------------------
.data

; describe the objects inside the DLL
ClassMap    ClassItem \ ; class map instance  
     { pCLSID_AsmCtrl,              DISPINTERFACE + SUPPLY_TYPE_INFO,   \
       OFFSET AsmCtrlTypeLibInfo,   OFFSET AsmCtrlIMap,     \
       OFFSET CreateAsmCtrl,        OFFSET DestroyAsmCtrl,  \
       OFFSET  AsmCtrlInitData,     SIZEOF AsmCtrlObject }
       END_CLASS_MAP

AsmCtrlIMap          \
    InterfaceItem       { pIID_IAsmCtrl,              OFFSET vtable.IAsmCtrl }
    InterfaceItem       { pIID_IOleObject,             OFFSET vtable.IOleObject }
    InterfaceItem       { pIID_IProvideClassInfo,      OFFSET vtable.IProvideClassInfo }
    InterfaceItem       { pIID_IPersist,               OFFSET vtable.IPersist }
    InterfaceItem       { pIID_IPersistStreamInit,     OFFSET vtable.IPersistStreamInit }
    InterfaceItem       { pIID_IViewObject,            OFFSET vtable.IViewObject }
    InterfaceItem       { pIID_IViewObject2,           OFFSET vtable.IViewObject }
; todo:
;   InterfaceItem       { pIID_ISpecifyPropertyPages,  OFFSET vtable.ISpecifyPropertyPages }
    InterfaceItem       { pIID_IPersistPropertyBag,    OFFSET vtable.IPersistPropertyBag }
    InterfaceItem       { pIID_ICategorizeProperties,  OFFSET vtable.ICategorizeProperties }
    END_INTERFACE_MAP

AsmCtrlTypeLibInfo  TypeLibInfo      {pLIBID_AsmCtrl, 1, 0}     

AsmCtrlData STRUCT
    m_isDirty           DWORD   0
    m_advf              DWORD   0
    m_pClientSite       DWORD   0
    m_pViewAdviseSink   DWORD   0
    m_pAdviseHolder     DWORD   0
    m_himetricExtent    SIZEL   {3968, 3968}
    m_pixelExtent       SIZEL   {150, 150 }
    m_Value             DWORD   85
    m_BackColor         DWORD   0808080H
    m_ForeColor         DWORD   0FFFFFFH
AsmCtrlData ENDS

AsmCtrlObject    STRUCT
    ObjectData0     ObjectData      { }     ; base values
    AsmCtrlData0    AsmCtrlData     { }     ; custom object data
    ObjectEntry0    ObjectEntry     { }     ; delegated Unknown
    ObjectEntry1    ObjectEntry     { }     ; IAsmCtrl
    ObjectEntry2    ObjectEntry     { }     ; IOleObject
    ObjectEntry3    ObjectEntry     { }     ; IProvideClassInfo
    ObjectEntry4    ObjectEntry     { }     ; IPersist
    ObjectEntry5    ObjectEntry     { }     ; IPersistStreamInit
    ObjectEntry6    ObjectEntry     { }     ; IViewObject
    ObjectEntry7    ObjectEntry     { }     ; IViewObject2
; todo:
;   ObjectEntry8    ObjectEntry     { }     ; ISpecifyPropertyPages
    ObjectEntry9    ObjectEntry     { }     ; IPersistPropertyBag
    ObjectEntry10   ObjectEntry     { }     ; ICategorizeProperties
AsmCtrlObject    ENDS

vtable                      _vtable {}

; define the interface IID's
DeclareGuid IID_IAsmCtrl
DeclareGuid CLSID_AsmCtrl
DeclareGuid LIBID_AsmCtrl
DeclareGuid IID_IOleObject
DeclareGuid IID_IProvideClassInfo
DeclareGuid IID_IPersist
DeclareGuid IID_IPersistStreamInit
DeclareGuid IID_IViewObject
DeclareGuid IID_IViewObject2
DeclareGuid IID_ISpecifyPropertyPages
DeclareGuid IID_IPersistPropertyBag
DeclareGuid IID_IOleControlSite
DeclareGuid IID_ICategorizeProperties
DeclareGuid IID_IOleWindow

DeclareGuid CLSID_StockFontPage
DeclareGuid CLSID_StockColorPage

HIMETRIC_PER_PIXEL  REAL4   26.458333

packedDW UNION 
    value DWORD     ? 
    STRUCT 
        loword WORD     ? 
        hiword WORD     ?    
    ENDS 
packedDW ENDS

PropCatItem     STRUCT
    m_dispid        DWORD   0
    m_CatID         DWORD   0
PropCatItem     ENDS

CatNameItem     STRUCT
    m_CatID         DWORD   0
    m_ResourceID    DWORD   0
CatNameItem     ENDS

END_CAT_MAP     MACRO 
    LOCAL  NullCatItem
    NullCatItem CatNameItem {0,0}
    ENDM

AsmCtrlPropMap          PropCatItem     { 0,                1}
    PropCatItem2        PropCatItem     { 1,                1}
    PropCatItem3        PropCatItem     { DISPID_FORECOLOR, 1}
    PropCatItem4        PropCatItem     { DISPID_BACKCOLOR, 1}
    PropCatItem5        PropCatItem     { DISPID_ABOUTBOX,  1}
    END_CAT_MAP

AsmCtrlCatNameMap       PropCatItem     { 1, IDS_AsmCtrl}
    END_CAT_MAP

AsmCtrlInitData STRUCT
    m_pAsmCtrlPropMap       DWORD   0
    m_pAsmCtrlCatNameMap    DWORD   0
AsmCtrlInitData ENDS

IDD_ABOUT               EQU     1000
IDC_OK                  EQU     1001
IDC_STATIC1             EQU     1002
IDC_STATIC2             EQU     1003
IDD_ABOUT_BITMAP        EQU     1005
IDB_ABOUT               EQU     2000
IDS_AsmCtrl             EQU     3000

AsmCtrlInitData1    AsmCtrlInitData     { OFFSET AsmCtrlPropMap, OFFSET AsmCtrlCatNameMap}

szClassName         BYTE        "ABOUT_MYCTRL2", 0
szAppName1          BYTE        "About My Control", 0
szAbout             BYTE        "Super-cheap About box for My Control", 0

szName              BYTE        "My Control", 0
NameLength          DWORD       10           
szAboutBox          byte        "ABOUTBOX", 0


;IDC_OK              EQU         1000

; names for storage values (in stream order)
wszValue            wchar       L(<Value\0>)
wszBackColor        wchar       L(<BackColor\0>)
wszForeColor        wchar       L(<ForeColor\0>)

; Property names
wszAsmCtrl          wchar       L(<Asm Control 2\0>)


;--------------------------------------------------------------------------
; prototypes
;HimetricToPixel     PROTO   :DWORD
;PixelToHimetric     PROTO   :DWORD
aboutBoxProc        PROTO   :DWORD, :DWORD, :packedDW, :packedDW
SendViewChange      PROTO   :DWORD


;--------------------------------------------------------------------------
.code

;--------------------------------------------------------------------------
;IAsmCtrl
CreateAsmCtrl PROC this_:DWORD
LOCAL pAH:DWORD

    pObjectData this_, ecx  ; cast this_ to CreateAsmCtrl object data
    xor eax, eax                                ; get variable
    mov pAH, eax
    mov (AsmCtrlData ptr [ecx]).m_isDirty, eax
    mov (AsmCtrlData ptr [ecx]).m_pClientSite, eax
    mov (AsmCtrlData ptr [ecx]).m_pViewAdviseSink, eax
    mov (AsmCtrlData ptr [ecx]).m_pAdviseHolder, eax
    mov (AsmCtrlData ptr [ecx]).m_himetricExtent.x, eax
    mov (AsmCtrlData ptr [ecx]).m_himetricExtent.y, eax
    mov (AsmCtrlData ptr [ecx]).m_pixelExtent.x, eax
    mov (AsmCtrlData ptr [ecx]).m_pixelExtent.y, eax
    mov (AsmCtrlData ptr [ecx]).m_Value, eax
    invoke CreateOleAdviseHolder, ADDR pAH
    xor eax, eax                                ; return S_OK
    ret
CreateAsmCtrl ENDP

;--------------------------------------------------------------------------
DestroyAsmCtrl PROC this_:DWORD
    LOCAL pBase:DWORD

    pObjectData this_, ecx  ; cast this_ to CreateAsmCtrl object data
    mov pBase, ecx
    mov ecx, pBase
    invoke ComPtrAssign, ADDR (AsmCtrlData ptr [ecx]).m_pClientSite, NULL
    mov ecx, pBase
    invoke ComPtrAssign, ADDR (AsmCtrlData ptr [ecx]).m_pViewAdviseSink, NULL
    mov ecx, pBase
    mov eax, (AsmCtrlData ptr [ecx]).m_pAdviseHolder
    .IF eax
        coinvoke (AsmCtrlData ptr [ecx]).m_pAdviseHolder, IUnknown, Release
    .ENDIF
    mov ecx, pBase
    xor eax, eax                                ; return S_OK
    ret
DestroyAsmCtrl ENDP

;--------------------------------------------------------------------------
put_Value PROC this_:DWORD, newVal:DWORD

    pObjectData this_, edx
    mov (AsmCtrlData ptr [edx]).m_isDirty, TRUE
    mov eax, newVal
    mov (AsmCtrlData ptr [edx]).m_Value, eax
    xor eax, eax
    ret
put_Value ENDP

;--------------------------------------------------------------------------
get_Value PROC this_:DWORD, pVal:DWORD

    pObjectData this_, edx
    mov eax, (AsmCtrlData ptr [edx]).m_Value
    mov ecx, pVal
    mov [ecx], eax
    xor eax, eax
    ret
get_Value ENDP

;--------------------------------------------------------------------------
Raise PROC this_:DWORD, Value:DWORD

    pObjectData this_, edx
    mov (AsmCtrlData ptr [edx]).m_isDirty, TRUE
    mov eax, (AsmCtrlData ptr [edx]).m_Value
    add eax, Value
    pObjectData this_, edx
    mov (AsmCtrlData ptr [edx]).m_Value, eax
    xor eax, eax    ;		return S_OK
    ret
Raise ENDP

;--------------------------------------------------------------------------
put_ForeColor PROC this_:DWORD, NewColor:DWORD

    pObjectData this_, ecx
    mov (AsmCtrlData ptr [ecx]).m_isDirty, TRUE
    mov eax, NewColor
    mov (AsmCtrlData ptr [ecx]).m_ForeColor, eax
    invoke SendViewChange, this_
    xor eax, eax    ;		return S_OK
    ret
put_ForeColor  ENDP

;--------------------------------------------------------------------------
get_ForeColor PROC this_:DWORD, pColor:DWORD

    .IF !pColor
        mov eax, E_POINTER
        ret
    .ENDIF
    pObjectData this_, ecx
    mov eax, (AsmCtrlData ptr [ecx]).m_ForeColor
    mov ecx, pColor
    mov [ecx], eax
    xor eax, eax    ;		return S_OK
    ret
get_ForeColor  ENDP

;--------------------------------------------------------------------------
put_BackColor PROC this_:DWORD, NewColor:DWORD

    pObjectData this_, ecx
    mov (AsmCtrlData ptr [ecx]).m_isDirty, TRUE
    mov eax, NewColor
    mov (AsmCtrlData ptr [ecx]).m_BackColor, eax
    invoke SendViewChange, this_
    xor eax, eax    ;		return S_OK
    ret
put_BackColor  ENDP

;--------------------------------------------------------------------------
get_BackColor PROC this_:DWORD, pColor:DWORD
    .IF !pColor
        mov eax, E_POINTER
        ret
    .ENDIF
    pObjectData this_, ecx
    mov eax, (AsmCtrlData ptr [ecx]).m_BackColor
    mov ecx, pColor
    mov [ecx], eax
    xor eax, eax    ;		return S_OK
    ret
get_BackColor  ENDP

;--------------------------------------------------------------------------
AboutBox  PROC this_:DWORD
    LOCAL pContainer:DWORD, pOleWindow:DWORD, hwnd:DWORD, wc:WNDCLASSEX
    LOCAL rect:RECT, Wwd:DWORD, Wht:DWORD, Wtx:DWORD, Wty:DWORD, hDlg:DWORD

    ; define the dialog box class
    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET aboutBoxProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,DLGWINDOWEXTRA
    push  g_hModule
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_BTNFACE+1
    mov   wc.lpszMenuName,NULL                          ;OFFSET MenuName
    mov   wc.lpszClassName,OFFSET szAboutBox
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc
    
    mov hwnd, NULL
    pObjectData this_, ecx
    mov eax, (AsmCtrlData ptr [ecx]).m_pClientSite
    .IF eax
        coinvoke (AsmCtrlData ptr [ecx]).m_pClientSite, IOleClientSite, GetContainer, ADDR pContainer
        .IF_SUCCEEDED
            coinvoke pContainer, IUnknown, QueryInterface, pIID_IOleWindow, ADDR pOleWindow
            .IF_SUCCEEDED
                coinvoke pOleWindow, IOleWindow, GetWindow, ADDR hwnd
                coinvoke pOleWindow, IOleWindow, Release
            .ENDIF
            coinvoke pContainer, IOleClientSite, Release
        .ENDIF                    
    .ENDIF
    invoke DialogBoxParam, g_hModule, IDD_ABOUT, hwnd, ADDR aboutBoxProc, NULL
    xor eax, eax    ;		return S_OK
    ret
AboutBox ENDP

;--------------------------------------------------------------------------
aboutBoxProc PROC hwnd:DWORD, message:DWORD, wparam:packedDW, lparam:packedDW

    .IF message == WM_COMMAND
        .IF wparam.loword == IDC_OK
		invoke EndDialog, hwnd, 0
        .ENDIF
    .ELSE
        invoke DefWindowProc, hwnd, message, wparam.value, lparam.value 
        ret
    .ENDIF
    xor eax, eax
    ret
aboutBoxProc ENDP

;--------------------------------------------------------------------------
SendViewChange PROC this_:DWORD

    pObjectData this_, ecx
    mov eax, (AsmCtrlData ptr [ecx]).m_pViewAdviseSink
    .IF eax
        coinvoke (AsmCtrlData ptr [ecx]).m_pViewAdviseSink, IAdviseSink, OnViewChange, DVASPECT_CONTENT, -1
    .ENDIF
    pObjectData this_, ecx
    mov eax, (AsmCtrlData ptr [ecx]).m_advf
    and eax, ADVF_ONLYONCE
    .IF eax
        invoke ComPtrAssign, ADDR (AsmCtrlData ptr [ecx]).m_pViewAdviseSink, NULL
        mov (AsmCtrlData ptr [ecx]).m_advf, NULL
    .ENDIF
    ret
SendViewChange ENDP

;--------------------------------------------------------------------------
;IOleObject

;--------------------------------------------------------------------------
IOleObject_SetClientSite PROC  this_:DWORD, pClientSite:DWORD

    pObjectData this_, ecx
    invoke ComPtrAssign, ADDR (AsmCtrlData ptr [ecx]).m_pClientSite, pClientSite

    xor eax, eax    ;		return S_OK
    ret
IOleObject_SetClientSite ENDP

;--------------------------------------------------------------------------
IOleObject_GetClientSite PROC this_:DWORD, ppClientSite:DWORD

    .IF !ppClientSite
        mov eax, E_POINTER
        ret
    .ENDIF
    pObjectData this_, edx
    invoke ComPtrAssign, ppClientSite, (AsmCtrlData  ptr [edx]).m_pClientSite
    xor eax, eax    ;		return S_OK
    ret
IOleObject_GetClientSite ENDP
 
;--------------------------------------------------------------------------
IOleObject_SetHostNames PROC this_:DWORD, lpcolestr:DWORD

    xor eax, eax    ;		return S_OK
    ret
IOleObject_SetHostNames ENDP

;--------------------------------------------------------------------------
IOleObject_Close PROC this_:DWORD, dwSaveOption:DWORD 
    LOCAL pBase:DWORD

    pObjectData this_, ecx
    mov pBase, ecx
    .IF (dwSaveOption == OLECLOSE_SAVEIFDIRTY) || (dwSaveOption == OLECLOSE_PROMPTSAVE)
        mov eax, (AsmCtrlData ptr [ecx]).m_isDirty 
        .IF eax
            coinvoke (AsmCtrlData ptr [ecx]).m_pClientSite, IOleClientSite, SaveObject
        .ENDIF
    .ENDIF
    mov ecx, pBase
    mov eax, (AsmCtrlData ptr [ecx]).m_pViewAdviseSink
    .IF eax 
        coinvoke (AsmCtrlData ptr [ecx]).m_pViewAdviseSink, IAdviseSink, OnClose
    .ENDIF
    mov ecx, pBase
    mov eax, (AsmCtrlData ptr [ecx]).m_pAdviseHolder
    .IF eax 
      coinvoke (AsmCtrlData ptr [ecx]).m_pAdviseHolder, IOleAdviseHolder, SendOnClose
    .ENDIF
    mov ecx, pBase
    mov eax, (AsmCtrlData ptr [ecx]).m_pClientSite
    .IF eax
        coinvoke (AsmCtrlData ptr [ecx]).m_pClientSite, IOleClientSite, Release
    .ENDIF
    xor eax, eax    ;		return S_OK
    ret
IOleObject_Close ENDP

;--------------------------------------------------------------------------
IOleObject_SetMoniker PROC this_:DWORD, IMoniker:DWORD

    mov eax, E_NOTIMPL
    ret
IOleObject_SetMoniker ENDP

;--------------------------------------------------------------------------
IOleObject_GetMoniker PROC this_:DWORD, A1:DWORD, A2:DWORD, ppMoniker:DWORD

    .IF ppMoniker
         mov ecx, ppMoniker     ; NULL the pointer sent us
         xor eax, eax
         mov [ecx], eax
    .ENDIF
    mov eax, E_NOTIMPL
    ret
IOleObject_GetMoniker ENDP
 
;--------------------------------------------------------------------------
IOleObject_InitFromData PROC this_:DWORD, pIDataObject:DWORD, A1:BOOL, A2:DWORD

    mov eax, E_NOTIMPL
    ret
IOleObject_InitFromData ENDP

;--------------------------------------------------------------------------
IOleObject_GetClipboardData PROC this_:DWORD, A1:DWORD, pIDataObject:DWORD

    mov eax, E_NOTIMPL
    ret
IOleObject_GetClipboardData ENDP

;--------------------------------------------------------------------------
IOleObject_DoVerb PROC this_:DWORD, iVerb:DWORD, lpmsg:MSG, pIOleClientSite:DWORD, lindex:DWORD, hwndParent:DWORD, lprcPosRect:DWORD
    LOCAL pControlSite:DWORD, hr:DWORD

    .IF iVerb == OLEIVERB_PROPERTIES
        pObjectData this_, ecx
        mov eax, (AsmCtrlData ptr [ecx]).m_pClientSite
        .IF eax
            coinvoke (AsmCtrlData ptr [ecx]).m_pClientSite, IOleClientSite, QueryInterface, pIID_IOleControlSite, ADDR pControlSite
            .IF_SUCCEEDED
                coinvoke pControlSite, IOleControlSite, ShowPropertyFrame
                ret
            .ELSE
                mov eax, E_FAIL
                ret
            .ENDIF
        .ENDIF
    .ELSEIF iVerb == 1          ; requested the AboutBox
        invoke AboutBox, this_
        mov eax, eax            ; return S_OK
    .ENDIF
    ret
IOleObject_DoVerb ENDP

;--------------------------------------------------------------------------
IOleObject_EnumVerbs PROC this_:DWORD, pIEnumOLEVERB:DWORD

    invoke OleRegEnumVerbs, pCLSID_AsmCtrl,  pIEnumOLEVERB
    ret
IOleObject_EnumVerbs ENDP

;--------------------------------------------------------------------------
IOleObject_Update PROC this_:DWORD

    xor eax, eax            ; return S_OK
    ret
IOleObject_Update ENDP

;--------------------------------------------------------------------------
IOleObject_IsUpToDate PROC this_:DWORD

    xor eax, eax            ; return S_OK
    ret
IOleObject_IsUpToDate ENDP

;--------------------------------------------------------------------------
IOleObject_GetUserClassID PROC this_:DWORD, pClsid:DWORD

    .IF !pClsid
        mov eax, E_POINTER
        ret
    .ENDIF
    mov ecx, pClsid 
    mov eax, pCLSID_AsmCtrl
    mov [ecx], eax
    xor eax, eax            ; return S_OK
    ret
IOleObject_GetUserClassID ENDP

;--------------------------------------------------------------------------
IOleObject_GetUserType PROC this_:DWORD, dwFormOfType:DWORD, pszUserType:DWORD 

    invoke OleRegGetUserType, pCLSID_AsmCtrl, dwFormOfType, pszUserType
    ret
IOleObject_GetUserType ENDP

;--------------------------------------------------------------------------
IOleObject_SetExtent PROC this_:DWORD, dwAspect:DWORD, pSizel:DWORD 
    LOCAL  temp:DWORD

    .IF !pSizel
        mov eax, E_POINTER
        ret
    .ENDIF
    .IF (dwAspect != DVASPECT_CONTENT) 
        mov eax, E_FAIL
    .ELSE
        pObjectData this_, edx
        mov ecx, pSizel
        ; get 'x' extents
        mov eax, (SIZEL PTR [ecx]).x
        mov (AsmCtrlData ptr [edx]).m_himetricExtent.x, eax
;        fninit                      ; init coprocessor
        fild (SIZEL PTR [ecx]).x    ; mov sizy.x to stack
        fdiv HIMETRIC_PER_PIXEL     ; divide by const
        fistp temp                  ; get integer result (rounds it too)
        mov eax, temp               ; leave in reg
        mov (AsmCtrlData ptr [edx]).m_pixelExtent.x, eax
        .IF eax < 10
            mov (AsmCtrlData ptr [edx]).m_pixelExtent.x, 10
            mov (AsmCtrlData ptr [edx]).m_himetricExtent.x, 265
        .ENDIF
        ; get 'y' extents
        mov eax, (SIZEL PTR [ecx]).y
        mov (AsmCtrlData ptr [edx]).m_himetricExtent.y, eax
;        fninit                      ; init coprocessor
        fild (SIZEL PTR [ecx]).y    ; mov sizy.y to stack
        fdiv HIMETRIC_PER_PIXEL     ; divide by const
        fistp temp                  ; get integer result (rounds it too)
        mov eax, temp               ; leave in reg
        mov (AsmCtrlData ptr [edx]).m_pixelExtent.y, eax
        .IF eax < 10
            mov (AsmCtrlData ptr [edx]).m_pixelExtent.y, 10
            mov (AsmCtrlData ptr [edx]).m_himetricExtent.y, 265
        .ENDIF
        xor eax, eax            ; return S_OK
    .ENDIF
    ret
IOleObject_SetExtent ENDP
;--------------------------------------------------------------------------

 ; 
 ; 
 ; ;const float HIMETRIC_PER_PIXEL(26.4583333333f);
 ; 
 ; HimetricToPixel PROC  psize:DWORD
 ;     LOCAL  temp:DWORD
 ; 
 ;     ; convert psize to .x in eax, .y in ecx
 ;     mov edx, psize
 ;     FNINIT                      ; init coprocessor
 ;     fild (SIZEL PTR [edx]).x    ; mov sizy.x to stack
 ;     fdiv HIMETRIC_PER_PIXEL     ; divide by const
 ;     fistp temp                  ; get integer result (rounds it too)
 ;     mov eax, temp               ; leave in reg
 ;     fild (SIZEL PTR [edx]).y    ; do same for sizy.y
 ;     fdiv HIMETRIC_PER_PIXEL
 ;     fistp temp 
 ;     mov ecx, temp
 ;     ret
 ; HimetricToPixel ENDP
 ; 
 ; PixelToHimetric PROC psize:DWORD
 ;     LOCAL  temp:DWORD
 ; 
 ;     ; convert psize to .x in eax, .y in ecx
 ;     mov edx, psize
 ;     FNINIT                      ; init coprocessor
 ;     fild (SIZEL PTR [edx]).x    ; mov sizy.x to stack
 ;     fmul HIMETRIC_PER_PIXEL     ; mult by const
 ;     fistp temp                  ; get integer result (rounds it too)
 ;     mov eax, temp               ; leave in reg
 ;     fild (SIZEL PTR [edx]).y    ; do same for sizy.y
 ;     fmul HIMETRIC_PER_PIXEL
 ;     fistp temp 
 ;     mov ecx, temp
 ;     ret
 ; PixelToHimetric ENDP
 ; 
;--------------------------------------------------------------------------
IOleObject_GetExtent PROC this_:DWORD, dwAspect:DWORD, pSizel:DWORD 

    .IF !pSizel
        mov eax, E_POINTER
        ret
    .ENDIF
    .IF (dwAspect != DVASPECT_CONTENT) 
        mov eax, E_INVALIDARG
    .ELSE
        pObjectData this_, edx
        mov ecx, pSizel 
        mov eax, (AsmCtrlData ptr [edx]).m_himetricExtent.x
        mov (SIZEL PTR [ecx]).x, eax
        mov eax, (AsmCtrlData ptr [edx]).m_himetricExtent.y
        mov (SIZEL PTR [ecx]).y, eax
        xor eax, eax            ; return S_OK
    .ENDIF
    ret
IOleObject_GetExtent ENDP

;--------------------------------------------------------------------------
IOleObject_Advise PROC this_:DWORD, pAdvSink:DWORD, pdwConnection:DWORD

    pObjectData this_, ecx
    coinvoke (AsmCtrlData ptr [ecx]).m_pAdviseHolder, IOleAdviseHolder, Advise, pAdvSink, pdwConnection
    ret
IOleObject_Advise ENDP

;--------------------------------------------------------------------------
IOleObject_Unadvise PROC this_:DWORD, dwConnection:DWORD 

    pObjectData this_, ecx
    coinvoke (AsmCtrlData ptr [ecx]).m_pAdviseHolder, IOleAdviseHolder, Unadvise, dwConnection
    ret
IOleObject_Unadvise ENDP

;--------------------------------------------------------------------------
IOleObject_EnumAdvise PROC this_:DWORD, ppEnumAdvise:DWORD

    pObjectData this_, ecx
    coinvoke (AsmCtrlData ptr [ecx]).m_pAdviseHolder, IOleAdviseHolder, EnumAdvise, ppEnumAdvise
    ret
IOleObject_EnumAdvise ENDP

;--------------------------------------------------------------------------
IOleObject_GetMiscStatus PROC this_:DWORD, dwAspect:DWORD, pdwStatus:DWORD 

    mov ecx, pdwStatus
    .IF !pdwStatus
        mov eax, E_POINTER
        ret
    .ENDIF
    .IF (dwAspect != DVASPECT_CONTENT) 
        xor eax, eax
        mov [ecx], eax
        mov eax, E_FAIL
    .ELSE
        mov eax, 131073
        mov [ecx], eax
        xor eax, eax            ; return S_OK
    .ENDIF
    ret
IOleObject_GetMiscStatus ENDP

;--------------------------------------------------------------------------
IOleObject_SetColorScheme PROC this_:DWORD, plogpalette:DWORD

    mov eax, E_NOTIMPL
    ret
IOleObject_SetColorScheme ENDP

;--------------------------------------------------------------------------
;IProvideClassInfo

;--------------------------------------------------------------------------
IProvideClassInfo_GetClassInfo PROC this_:DWORD, ppTI:DWORD

    .IF !ppTI
        mov eax, E_POINTER
        ret
    .ENDIF
    mov ecx, (ObjectEntry  PTR this_).m_pBase
    mov ecx, (ObjectData PTR [ecx]).m_pti
    .IF !ecx
        ret
    .ENDIF
    mov edx, ppTI
    mov [edx], ecx
    coinvoke ppTI, IUnknown, AddRef
    xor eax, eax            ; return S_OK 
    ret
IProvideClassInfo_GetClassInfo ENDP

;--------------------------------------------------------------------------
;IPersistStreamInit

;--------------------------------------------------------------------------
IPersist_GetClassID PROC this_:DWORD, pClassID:DWORD

    .IF !pClassID
        mov eax, E_POINTER
        ret
    .ENDIF
    mov eax, pCLSID_AsmCtrl
    mov [ecx], eax
    xor eax, eax            ; return S_OK    
    ret
IPersist_GetClassID ENDP

;--------------------------------------------------------------------------
IPersistStreamInit_IsDirty PROC this_:DWORD

    pObjectData this_, ecx
    mov eax, (AsmCtrlData ptr [ecx]).m_isDirty
    .IF eax
        xor eax, eax    ; mov eax, S_OK
    .ELSE
        mov eax, S_FALSE
    .ENDIF
    ret
IPersistStreamInit_IsDirty ENDP

;--------------------------------------------------------------------------
IPersistStreamInit_Load PROC this_:DWORD, pStream:DWORD
    LOCAL var:VARIANT, bCount:DWORD,    pBase:DWORD

    pObjectData this_, ecx
    mov pBase, ecx

 ;  persisted quantities and order
 ;  m_Value
 ;  m_BackColor
 ;  m_ForeColor
    
    coinvoke pStream, IStream, Read, ADDR (AsmCtrlData ptr [ecx]).m_Value, 4, ADDR bCount
    mov ecx, pBase
    coinvoke pStream, IStream, Read, ADDR (AsmCtrlData ptr [ecx]).m_BackColor, 4, ADDR bCount
    mov ecx, pBase
    coinvoke pStream, IStream, Read, ADDR (AsmCtrlData ptr [ecx]).m_ForeColor, 4, ADDR bCount

    xor eax, eax            ; return S_OK 
    ret
IPersistStreamInit_Load ENDP

;--------------------------------------------------------------------------
IPersistStreamInit_Save PROC this_:DWORD, pStream:DWORD, fClearDirty:DWORD
    LOCAL   bCount:DWORD, pBase:DWORD

    pObjectData this_, ecx
    mov pBase, ecx
    .IF fClearDirty
        mov (AsmCtrlData ptr [ecx]).m_isDirty, FALSE
    .ENDIF
    mov ecx, pBase
    coinvoke pStream, ISequentialStream, Write, ADDR (AsmCtrlData ptr [ecx]).m_Value, SIZEOF DWORD, ADDR bCount

    mov ecx, pBase
    coinvoke pStream, ISequentialStream, Write, ADDR (AsmCtrlData ptr [ecx]).m_BackColor, SIZEOF DWORD, ADDR bCount

    mov ecx, pBase
    coinvoke pStream, ISequentialStream, Write, ADDR (AsmCtrlData ptr [ecx]).m_ForeColor, SIZEOF DWORD, ADDR bCount

    xor eax, eax            ; return S_OK 
    ret
IPersistStreamInit_Save ENDP

;--------------------------------------------------------------------------
IPersistStreamInit_GetSizeMax PROC this_:DWORD, pSize:DWORD 
    LOCAL ssize:ULARGE_INTEGER

    .IF !pSize
        mov eax, E_POINTER
        ret
    .ENDIF
    mov eax, 1000
    mov ssize.LowPart, eax
    xor eax, eax
    mov ssize.HighPart, eax
    mov eax, pSize
    lea ecx, ssize
    mov [eax], ecx   
    xor eax, eax            ; return S_OK    
    ret
IPersistStreamInit_GetSizeMax ENDP

;--------------------------------------------------------------------------
IPersistStreamInit_InitNew PROC this_:DWORD

    pObjectData this_, ecx
    mov eax, 3969
    mov (AsmCtrlData ptr [ecx]).m_himetricExtent.x, eax
    mov (AsmCtrlData ptr [ecx]).m_himetricExtent.y, eax
    mov eax, 150
    mov (AsmCtrlData ptr [ecx]).m_pixelExtent.x, eax
    mov (AsmCtrlData ptr [ecx]).m_pixelExtent.y, eax
    mov eax, 0808080H
    mov (AsmCtrlData ptr [ecx]).m_ForeColor, eax
    mov eax, 0FFFFFFH
    mov (AsmCtrlData ptr [ecx]).m_BackColor, eax
    xor eax, eax            ; return S_OK 
    ret
IPersistStreamInit_InitNew ENDP

;--------------------------------------------------------------------------
;IViewObject

;--------------------------------------------------------------------------
IViewObject_Draw PROC PROC this_:DWORD, dwAspect:DWORD, lindex:DWORD, 
                           pvAspect:DWORD, ptd:DWORD, hicTargetDev:DWORD, 
                           hdc:DWORD, pRectBounds:DWORD, prcWBounds:DWORD,
                           pfnContinue:DWORD, dwContinue:DWORD 
    LOCAL  hBrush:DWORD

    .IF dwAspect != DVASPECT_CONTENT
        mov eax, DV_E_DVASPECT
        ret
    .ENDIF
    pObjectData this_, ecx
    mov eax, (AsmCtrlData ptr [ecx]).m_BackColor
    invoke CreateSolidBrush, eax
    mov hBrush, eax
    invoke FillRect, hdc, pRectBounds, hBrush
    invoke DeleteObject, hBrush
    pObjectData this_, ecx
    mov eax, (AsmCtrlData ptr [ecx]).m_ForeColor
    invoke SetTextColor, hdc, eax
    pObjectData this_, ecx
    mov eax, (AsmCtrlData ptr [ecx]).m_BackColor
    invoke SetBkColor, hdc, eax
    invoke DrawText, hdc, ADDR szName, NameLength, pRectBounds, DT_CENTER or DT_VCENTER or DT_SINGLELINE
    xor eax, eax            ; return S_OK    
    ret
IViewObject_Draw ENDP

;--------------------------------------------------------------------------
IViewObject_GetColorSet PROC this_:DWORD, dwAspect:DWORD, lindex:DWORD, 
                           pvAspect:DWORD, ptd:DWORD, hicTargetDev:DWORD, 
                           ppColorSet:DWORD

    mov eax, E_NOTIMPL
    ret
IViewObject_GetColorSet	ENDP

;--------------------------------------------------------------------------
IViewObject_Freeze PROC this_:DWORD, dwAspect:DWORD, lindex:DWORD, 
                           pvAspect:DWORD, pdwFreeze:DWORD 
    mov eax, E_NOTIMPL
    ret
IViewObject_Freeze ENDP

;--------------------------------------------------------------------------
IViewObject_Unfreeze PROC this_:DWORD, dwFreeze:DWORD

    mov eax, E_NOTIMPL
    ret
IViewObject_Unfreeze ENDP

;--------------------------------------------------------------------------
IViewObject_SetAdvise PROC this_:DWORD, aspect:DWORD, advf:DWORD, ppViewAdviseSink:DWORD

    .IF aspect != DVASPECT_CONTENT
        mov eax, DV_E_DVASPECT
        ret
    .ENDIF
    pObjectData this_, edx
    mov ecx, ppViewAdviseSink
    invoke ComPtrAssign, ADDR (AsmCtrlData ptr [edx]).m_pViewAdviseSink, ecx
    mov eax, advf
    pObjectData this_, edx
    mov (AsmCtrlData ptr [edx]).m_advf, eax
    and eax, ADVF_PRIMEFIRST
    .IF eax
        invoke SendViewChange, this_
    .ENDIF
    xor eax, eax            ; return S_OK
    ret
IViewObject_SetAdvise ENDP

;--------------------------------------------------------------------------
IViewObject_GetAdvise PROC this_:DWORD, pAspects:DWORD, pAdvf:DWORD, ppViewAdviseSink:DWORD

    .IF !ppViewAdviseSink
        mov eax, E_POINTER
        ret
    .ENDIF
    pObjectData this_, edx
    invoke ComPtrAssign, ppViewAdviseSink, (AsmCtrlData ptr [edx]).m_pViewAdviseSink
    mov ecx, pAspects
    mov eax, [ecx]
    .IF eax == DVASPECT_CONTENT
        mov ecx, pAdvf
        mov eax, [ecx]
        .IF eax
            mov eax, (AsmCtrlData ptr [edx]).m_advf
            mov [ecx], eax
        .ENDIF
    .ENDIF
    xor eax, eax            ; return S_OK
    ret
IViewObject_GetAdvise ENDP	

;--------------------------------------------------------------------------
;IViewObject2
 
;--------------------------------------------------------------------------
IViewObject2_GetExtent PROC this_:DWORD, aspect:DWORD, lindex:DWORD, 
                           ptd:DWORD, pSize:DWORD 

    .IF !pSize
        mov eax, E_POINTER
        ret
    .ENDIF
    .IF (aspect != DVASPECT_CONTENT) 
        mov eax, DV_E_DVASPECT
        ret
    .ENDIF
    mov ecx, pSize 
    pObjectData this_, edx
    mov eax, DWORD PTR (AsmCtrlData ptr [edx]).m_himetricExtent
    mov [ecx], eax    
    xor eax, eax            ; return S_OK
    ret
IViewObject2_GetExtent ENDP

;--------------------------------------------------------------------------
;ISpecifyPropertyPages

;--------------------------------------------------------------------------
ISpecifyPropertyPages_GetPages PROC  this_:DWORD, pPages:DWORD

    .IF !pPages
        mov eax, E_POINTER
        ret
    .ENDIF
    mov edx, pPages
    mov (CAUUID PTR [edx]).cElems, 2
    invoke CoTaskMemAlloc, (SIZEOF GUID) * 2
    mov (CAUUID PTR [edx]).pElems, eax

    push esi
    push edi

    mov esi, pCLSID_StockFontPage
    mov edi, eax
    mov ecx, SIZEOF GUID / 4
    rep movsd

    mov esi, pCLSID_StockColorPage
    mov edi, eax
    mov ecx, SIZEOF GUID / 4
    rep movsd

    pop edi
    pop esi

    xor eax, eax            ; return S_OK
    ret
ISpecifyPropertyPages_GetPages ENDP

;--------------------------------------------------------------------------
;IPersistPropertyBag   

;--------------------------------------------------------------------------
IPersistPropertyBag_InitNew PROC this_:DWORD

    invoke IPersistStreamInit_InitNew, this_   ; re-use the method 
                                               ; (hey, THAT'S like inheritance!)
    ret
IPersistPropertyBag_InitNew ENDP

;--------------------------------------------------------------------------

IPersistPropertyBag_Load PROC this_:DWORD, pPropBag:DWORD, pErrorLog:DWORD 
    LOCAL var:VARIANT,    pBase:DWORD

    pObjectData this_, edx
    mov pBase, edx
    
 ;  persisted quantities and order
 ;  m_Value = Value
    
    mov var.vt, VT_I4
    mov var.lVal, 0
    coinvoke pPropBag, IPropertyBag, Read, ADDR wszValue, ADDR var, NULL
    .IF_SUCCEEDED
        mov edx, pBase
        mov eax, var.lVal
        mov (AsmCtrlData ptr [edx]).m_Value, eax
        .ELSE
    .ENDIF

    mov var.vt, VT_I4
    mov var.lVal, 0
    coinvoke pPropBag, IPropertyBag, Read, ADDR wszBackColor, ADDR var, NULL
    .IF_SUCCEEDED
        mov edx, pBase
        mov eax, var.lVal
        mov (AsmCtrlData ptr [edx]).m_BackColor, eax
        .ELSE
    .ENDIF

    mov var.vt, VT_I4
    mov var.lVal, 0
    coinvoke pPropBag, IPropertyBag, Read, ADDR wszForeColor, ADDR var, NULL
    .IF_SUCCEEDED
        mov edx, pBase
        mov eax, var.lVal
        mov (AsmCtrlData ptr [edx]).m_ForeColor, eax
        .ELSE
    .ENDIF
    xor eax, eax            ; return S_OK
    ret
IPersistPropertyBag_Load ENDP

;--------------------------------------------------------------------------
IPersistPropertyBag_Save PROC this_:DWORD, pPropBag:DWORD, fClearDirty:DWORD, fSaveAllProperties:DWORD
    LOCAL var:VARIANT,    pBase:DWORD

    pObjectData this_, ecx
    mov pBase, ecx
    .IF fClearDirty
        mov (AsmCtrlData ptr [ecx]).m_isDirty, FALSE
    .ENDIF    
 ;  persisted quantities and order
 ;  m_Value = Value
    
    mov var.vt, VT_I4
    mov eax, (AsmCtrlData ptr [ecx]).m_Value
    mov var.lVal, eax
    coinvoke pPropBag, IPropertyBag, Write, ADDR wszValue, ADDR var

    mov ecx, pBase
    mov var.vt, VT_I4
    mov eax, (AsmCtrlData ptr [ecx]).m_BackColor
    mov var.lVal, eax
    coinvoke pPropBag, IPropertyBag, Write, ADDR wszBackColor, ADDR var

    mov ecx, pBase
    mov var.vt, VT_I4
    mov eax, (AsmCtrlData ptr [ecx]).m_ForeColor
    mov var.lVal, eax
    coinvoke pPropBag, IPropertyBag, Write, ADDR wszForeColor, ADDR var

    xor eax, eax            ; return S_OK
    ret
IPersistPropertyBag_Save ENDP

;--------------------------------------------------------------------------
ICategorizeProperties_MapPropertyToCategory PROC this_:DWORD, dispid:DWORD, ppropcat:DWORD

    mov ecx, OFFSET AsmCtrlPropMap          
    mov edx, (PropCatItem PTR [ecx]).m_CatID
    .WHILE edx          ; a NULL CatID signals the end
        mov eax, (PropCatItem PTR [ecx]).m_dispid
        .IF eax == dispid
            ; we found a dispid we catagorize
            mov ecx, ppropcat
            mov [ecx], edx          ; return m_CatID
            xor eax, eax            ; return S_OK
            ret
        .ENDIF
        add ecx, SIZEOF PropCatItem
    .ENDW
    mov eax, E_FAIL
    ret
ICategorizeProperties_MapPropertyToCategory ENDP

;--------------------------------------------------------------------------
ICategorizeProperties_GetCategoryName PROC this_:DWORD, propcat:DWORD, lcid:DWORD, pbstrName:DWORD
    LOCAL Buf[MAX_PATH]:BYTE, wBuf[MAX_PATH]:WORD

    mov ecx, OFFSET AsmCtrlCatNameMap
    mov edx, (CatNameItem PTR [ecx]).m_ResourceID
    .WHILE edx          ; a NULL ResourceID signals the end
        mov eax, (CatNameItem PTR [ecx]).m_CatID
        .IF eax == propcat
            ; we found our catagory name index
            invoke LoadString, g_hModule, edx, ADDR Buf, MAX_PATH
            invoke MultiByteToWideChar, CP_ACP, 0, ADDR Buf, -1, ADDR wBuf, MAX_PATH
            invoke SysAllocString, ADDR wBuf
            mov ecx, pbstrName 
            mov [ecx], eax
            xor eax, eax            ; return S_OK
            ret
        .ENDIF
        add ecx, SIZEOF CatNameItem
    .ENDW
    mov eax, E_FAIL
    ret
ICategorizeProperties_GetCategoryName ENDP
;--------------------------------------------------------------------------

end DllMain
