;-------------------------------------------------------------------------------
;  colibrary procedure GetCachedTypeInfo 
;
; -------------------------------------------------------
; This procedure was written by Ernest Murphy    9/27/00
;
; 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\oleaut32.inc
include     \masm32\include\kernel32.inc
include     \masm32\COM\include\oaidl.inc
include     \masm32\COM\include\language.inc

include     colib.inc

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

GetCachedTypeInfo PROC PUBLIC this_:DWORD, lcid:DWORD, ppti:DWORD

;-------------------------------------------------------------------------------
; colib internal procedure 
; checks requested type lib lcid against the catched lcid
;  if equal, returns same
;
;  if not equal, releases catched type library, 
;                then instances new matching type library
;
;
; EXAMPLE:
; invoke GetCachedTypeInfo, this_, lcid, ADDR pti
;
; Uses: eax, ecx, edx
;
;-------------------------------------------------------------------------------

;--------------------------------------------------------------------------------------
    LOCAL ptl:DWORD, pti:DWORD
    LOCAL pbase:DWORD, pm_pti:DWORD, pm_lcid:DWORD
    LOCAL m_pIID_TYPELIB:DWORD,  m_MajorVer:DWORD, m_MinorVer:DWORD
    
    ; ptl     ptr to ITypeLib, used to get to ITypeLib
    ; pti     ptr to ITypeLib, used to get to ITypeInfo
    ; pbase   ptr to ObjectBase
    ; pm_pti  ptr to ObjectData.m_pti
    ; pm_lcid ptr to ObjectData.m_lcid

    ; make pointers to our ObjectData items of interest.
    mov edx, this_                                  ; get object
    mov edx, (ObjectEntry PTR[edx]).m_pBase         ; walk to base data
    mov pbase, edx
    lea ecx, (ObjectData PTR[edx]).m_lcid
    mov pm_lcid, ecx
    lea ecx, (ObjectData PTR[edx]).m_pti
    mov pm_pti, ecx
    ; check the given lcid with the last one we saw

 ; not so sure this feature is needed (or if it is just a bug)
	mov eax, lcid
	.IF (eax == LOCALE_SYSTEM_DEFAULT) || (!eax)
	  invoke GetSystemDefaultLCID
	.ELSEIF (eax == LOCALE_USER_DEFAULT)
	  invoke GetUserDefaultLCID
	.ENDIF
	; eax now has lcid in proper form
	mov lcid, eax
    mov ecx, pm_lcid
    mov ecx, [ecx]
    .IF ecx == eax
        jmp Goodpti                     ; we have this one cached
    .ENDIF
    mov ecx, pm_lcid
    mov eax, -1
    mov [ecx], eax           ; store a bad lcid
    mov ecx, pm_pti
    mov ecx, [ecx]
    .IF ecx    ; there is a pointer cached
        ; destroy the old type info pointer
        coinvoke ecx, IUnknown, Release
    .ENDIF
    mov edx, pbase
    mov edx, (ObjectData PTR[edx]).m_pClassItem    ; get map data
    mov edx, (ClassItem PTR[edx]).m_pTypeLibInfo   ; walk to ObjectItem.m_pTypeLibInfo
    mov ecx, [edx]
    mov m_pIID_TYPELIB, ecx
    mov ecx, [edx + 4]
    mov m_MajorVer, ecx
    mov ecx, [edx + 8]
    mov m_MinorVer, ecx
    invoke LoadRegTypeLib,  m_pIID_TYPELIB,  ; REFGUID rguid, 
                            m_MajorVer,      ; unsigned short wVerMajor, 
                            m_MinorVer,      ; unsigned short wVerMinor, 
                            lcid,            ; LCID lcid, 
                            ADDR ptl         ; ITypeLib FAR* FAR* pptlib 
    .IF_FAILED
        jmp NoLib
    .ENDIF
    coinvoke ptl, ITypeLib, GetTypeInfo, 0, ADDR pti  ;TKIND_DISPATCH
    mov pbase, eax      ; steal pbase as a temp storage for the retval
    coinvoke ptl, ITypeLib, Release
    mov eax, pbase      ; now test if we got a valid ITypeInfo
    .IF_FAILED
        jmp NoLib
    .ENDIF
    ; save the matched lcid
    mov eax, lcid
    mov edx, pm_lcid 
    mov [edx], eax              ; save which lcid was used
    ; save the matched pti
    mov edx, pm_pti
    mov ecx, pti
    mov [edx], ecx              ; save the ITypeInfo we have
    jmp Goodpti
NoLib:
    mov ecx, ppti
    xor eax, eax
    mov [ecx], eax              ; null ret ptr too
    mov eax, DISP_E_UNKNOWNLCID
    jmp return
Goodpti:
    ; return m_pti in ppti
    mov ecx, pm_pti
    
    mov ecx, [ecx]
    mov edx, ppti
    mov [edx], ecx              ; return the ITypeInfo we have
Goodpti2:   
    ; return S_OK
    xor eax, eax
return:
    ret
GetCachedTypeInfo ENDP
;-------------------------------------------------------------------------------

end
