;-------------------------------------------------------------------------------
;  colibrary procedure DllGetClassObject
; 
; -------------------------------------------------------
; This procedure was written by Ernest Murphy    9/27/00
;
;  revised 1/8/01 to reposition .data structs to other libs
;		
; Copyright (c) 9/28/00  Ernest Murphy
; For educational use only. Any commercial re-use only by written license
;
; -------------------------------------------------------
.NOLIST
.386
.model flat, stdcall  ; 32 bit memory model
option casemap :none  ; case sensitive

include     mini_win.inc	; 'just enough' of windows.inc (speeds build)
include     \masm32\include\kernel32.inc
include     \masm32\include\oleaut32.inc
include     \masm32\include\ole32.inc
include     \masm32\include\masm32.inc
include     \masm32\COM\include\oaidl.inc

include     colib.inc

externdef   ClassMap:DWORD
externdef	IID_IClassFactory:DWORD

;PUBLIC vtIClassFact
PUBLIC Pos          
PUBLIC pResEnd      

.data

ClassFactoryClassMap	EQU    CFClassMap

CFClassMap          ClassItem     { pIID_IClassFactory, NULL, NULL, \
                                    OFFSET CFIMap, NULL, NULL, \
                                    NULL, SIZEOF CFmembers }
                    END_CLASS_MAP        

CFIMap                  EQU      CFInterfaceItem1   
 
CFInterfaceItem1    InterfaceItem { pIID_IClassFactory, OFFSET vtIClassFact }
                    END_INTERFACE_MAP

vtIClassFact            IClassFactory \
     { NDQueryInterface,
       NDAddRef,
       NDRelease,
       CreateInstance,
       LockServer }

CFmembers   STRUCT  DWORD
    m_pClassItem   DWORD       NULL
CFmembers   ENDS

; declare the ClassFactory object structure
; this is only run-time instanced
ClassFactObject STRUCT  DWORD
    ObjectData0     ObjectData  { }     ; base values
    CFMembers       CFmembers   { }     ; info on the object to impliment
    ObjectEntry0    ObjectEntry { }     ; non-delegating Unknown
    ObjectEntry1    ObjectEntry { }     ; IClassFactory   
ClassFactObject ENDS

Pos                     DWORD           0
pResEnd                 DWORD           0


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

DllGetClassObject PROC PUBLIC rclsid:DWORD, riid:DWORD, ppv:DWORD
             
;-------------------------------------------------------------------------------
; COM server dll main export
;   Creates a Class Factory object to create a requested coclass
;   
;
; EXAMPLE:
;   invoke DllGetClassObject, ADDR clsid, ADDR iid:DWORD, ADDR pv
;
; Uses: eax, ecx, edx
;
;
;-------------------------------------------------------------------------------
    LOCAL pFactory:DWORD, pClassItem:DWORD, retval:DWORD

    ; compare the CLSID given us to the ones we can build
    ; we can ONLY build a Class Factory object to build the objects
    ; in our Class Map. All others get rejected

    mov pFactory, NULL      ; define our pointers
    ; walk the class map and see if we make this class object 
    mov ecx, OFFSET ClassMap
    mov pClassItem, ecx
    mov eax, (ClassItem PTR [ecx]).m_clsid       ; get first class clsid
    .WHILE eax	; check if Classitem.m_riid != NULL = END_OF_MAP signal
        invoke  IsEqualGUID, rclsid, eax
        .IF !eax
            add pClassItem, SIZEOF ClassItem    
            mov ecx, pClassItem
            mov eax, (ClassItem PTR [ecx]).m_clsid
        .ELSE
            ; found a supported class
            ; make a new Class Factory object
            ; create a Class Factory
            invoke AllocObject, ADDR pFactory, ADDR CFClassMap, NULL, NULL 
            .IF_FAILED
                mov eax, E_OUTOFMEMORY
                ret
            .ENDIF
            ;now set the custom data  (the reference 
			; to the Class Item we can create)
			mov eax, pFactory
            mov eax, (ObjectEntry PTR [eax]).m_pBase
            mov ecx, pClassItem 
            mov (ClassFactObject PTR [eax]).CFMembers.m_pClassItem, ecx
            coinvoke pFactory, IUnknown, QueryInterface, riid, ppv
            ; use the QI hresult to determine the success of this procedure
            mov retval, eax
            ; and release our helper pointer
            invoke NDRelease, pFactory
            mov eax, retval
            ret
        .ENDIF
    .ENDW
    ; if we got here we didn't find a matching CLSID
    mov eax, CLASS_E_CLASSNOTAVAILABLE
    ret
DllGetClassObject ENDP
;-------------------------------------------------------------------------------

end
