;; easycom.ahk ;; VERY beta v0.002 EASYCOM_DLL := "..\bin\easycom.dll" COM_VOID := 0x01 COM_SKIP := COM_VOID COM_INT := 0x10 COM_FLT := 0x12 COM_DBL := 0x16 COM_STR := 0x18 COM_OBJ := 0x1A COM_OBJ_UNKN := 0x1C COM_ARRAY := 0x1E COM_BYREF := 0x80 COM_TYPEMASK := 0x1F ;COM_VARIANT := 0x20 ; Under development COM_METHOD := 1 COM_PROPGET := 2 COM_PROPPUT := 3 COM_MAX_ARGS := 9 LoadEasyCOM() { global EASYCOM_DLL, g_iEasyCOMHandle g_iEasyCOMHandle := DllCall("LoadLibrary", "str", EASYCOM_DLL) If (g_iEasyCOMHandle = 0) { Msgbox % "Error loading EasyCOM.dll" ExitApp } } UnloadEasyCOM() { global g_iEasyCOMHandle DllCall("FreeLibrary", "UInt", g_iEasyCOMHandle) } CreateObject(sProgram_or_Class_Id) { global EASYCOM_DLL StringLeft, sFirstChar, sProgram_or_Class_Id, 1 If (sFirstChar = "{") iPtr := DllCall(EASYCOM_DLL . "\CreateObjectCLSID" , "str", sProgram_or_Class_Id) else iPtr := DllCall(EASYCOM_DLL . "\CreateObject" , "str", sProgram_or_Class_Id) If (iPtr = 0) ; Error during call! { Msgbox % "Error creating object '" . sProgram_or_Class_Id . "'`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") UnloadEasyCOM() Exit } Return iPtr } CreateObjectFromDll(sDll, ClassId) { global EASYCOM_DLL iPtr := DllCall(EASYCOM_DLL . "\CreateObjectFromDll" , "str", sDll , "str", ClassId) If (iPtr = 0) ; Error during call! { Msgbox % "Error creating object '" . sProgram_or_Class_Id . "'`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") UnloadEasyCOM() Exit } Return iPtr } GetObject(sProgram_or_Class_Id) { global EASYCOM_DLL StringLeft, sFirstChar, sProgram_or_Class_Id, 1 If (sFirstChar = "{") iPtr := DllCall(EASYCOM_DLL . "\GetObjectCLSID" , "str", sProgram_or_Class_Id) else iPtr := DllCall(EASYCOM_DLL . "\GetObject" , "str", sProgram_or_Class_Id) If (iPtr = 0) ; Error during call! { Msgbox % "Error getting object '" . sProgram_or_Class_Id . "'`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") UnloadEasyCOM() Exit } Return iPtr } ReleaseObject(iObjectPtr) { global EASYCOM_DLL iErr := Return DllCall(EASYCOM_DLL . "\ReleaseObject" , "int", iObjectPtr) If (iErr <> 1) { Msgbox % "Minor error with ReleaseObject: " iErr "`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") } } Invoke(iObjPtr, sMemberName , arg1="`b" , arg2="`b" , arg3="`b" , arg4="`b" , arg5="`b" , arg6="`b" , arg7="`b" , arg8="`b" , arg9="`b") { global EASYCOM_DLL, COM_MAX_ARGS, COM_STR iErr := 1 Critical, On ; <-- IMPORTANT! iErr := DllCall(EASYCOM_DLL . "\BeginMemberCall", "int", -1) If (iErr <> 1) ; Error during call! { Msgbox % "Error beginning member call`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") UnloadEasyCOM() Exit } Loop, %COM_MAX_ARGS% { symArg := "arg" . A_Index xVal := %symArg% If (xVal = "`b") Break iErr := DllCall(EASYCOM_DLL . "\AddArgument" , "int", COM_STR , "str", xVal) If (iErr <> 1) ; Error during call! { Msgbox % "Error adding argument " . A_Index . ": " . xVal . "`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") UnloadEasyCOM() Exit } } iMemberType := __MemberType(sMemberName) iType := DllCall(EASYCOM_DLL . "\Invoke" , "int", iObjPtr , "str", sMemberName , "int", iMemberType) If (iType < 1) ; Error during call! { sMsg := "Error in call to '" . sMemberName . "'`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") ; If an exception, show the exception info as well If (DllCall(EASYCOM_DLL . "\GetComErrorCode", "uint") = 0x80020009) sMsg := sMsg "`n" __GetExceptionInfo() Msgbox % sMsg UnloadEasyCOM() Exit ;DllCall(EASYCOM_DLL . "\EndMemberCall") ;Return } If (iType = 1) Return ; Nothing was returned iPtr := DllCall(EASYCOM_DLL . "\GetReturn") If (iPtr = 0) Return ; NULL pointer was returned sAHKType := __COMRetToAHKType(iType) xVal := DllCall(EASYCOM_DLL . "\GetReturn", %sAHKType%) DllCall(EASYCOM_DLL . "\EndMemberCall") Critical, Off Return xVal } InvokeEx(iObjPtr, sMemberName , type1=0, arg1=0 , type2=0, arg2=0 , type3=0, arg3=0 , type4=0, arg4=0 , type5=0, arg5=0 , type6=0, arg6=0 , type7=0, arg7=0 , type8=0, arg8=0 , type9=0, arg9=0) { global EASYCOM_DLL, COM_MAX_ARGS, COM_BYREF ;, COM_TYPEMASK ; to be included in InvokeByRef() iErr := 1 iArgCount := 0 Critical, On ; <-- IMPORTANT! iErr := DllCall(EASYCOM_DLL . "\BeginMemberCall", "int", -1) If (iErr <> 1) ; Error during call! { Msgbox % "Error beginning member call`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") UnloadEasyCOM() Exit } Loop, %COM_MAX_ARGS% { symArg := "type" . A_Index iType := %symArg% If (iType = 0) ; No more args? Break iArgCount++ sAHKType := __COMTypeToAHKType(iType) symArg := "arg" . A_Index xVal := %symArg% iErr := DllCall(EASYCOM_DLL . "\AddArgument" , "int", iType , %sAHKType%, xVal) If (iErr <> 1) ; Error during call! { Msgbox % "Error adding argument " . A_Index . ": " . xVal . "`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") UnloadEasyCOM() Exit } } iMemberType := __MemberType(sMemberName) iType := DllCall(EASYCOM_DLL . "\Invoke" , "int", iObjPtr , "str", sMemberName , "int", iMemberType) If (iType < 1) ; Error during call! { sMsg := "Error in call to '" . sMemberName . "'`n" . DllCall(EASYCOM_DLL . "\GetErrorDescription", "str") ; If an exception, show the exception info as well If (DllCall(EASYCOM_DLL . "\GetComErrorCode", "uint") = 0x80020009) sMsg := sMsg "`n" __GetExceptionInfo() Msgbox % sMsg UnloadEasyCOM() Exit } ; Update any parameters passed 'by reference' ; to be included in InvokeByRef() ;Loop, %iArgCount% ;{ ; symArg := "type" . A_Index ; iType := %symArg% ; If (iType & COM_BYREF) ; { ; symArg := "arg" . A_Index ; ; TODO: Add error checking ; %symArg% := DllCall(EASYCOM_DLL . "\GetArgument" ; , "int", A_Index ; , __COMRetToAHKType(iType & COM_TYPEMASK)) ; } ;} If (iType = 1) Return ; Nothing was returned iPtr := DllCall(EASYCOM_DLL . "\GetReturn") If (iPtr = 0) Return ; NULL pointer was returned sAHKType := __COMRetToAHKType(iType) xVal := DllCall(EASYCOM_DLL . "\GetReturn", %sAHKType%) DllCall(EASYCOM_DLL . "\EndMemberCall") Critical, Off Return xVal } ;; Internal Helper functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; __MemberType(ByRef sMemberName) { global COM_METHOD, COM_PROPGET, COM_PROPPUT StringRight, sMemberType, sMemberName, 2 If (sMemberType = "()") { iMemberType := COM_METHOD StringTrimRight, sMemberName, sMemberName, 2 } Else { StringRight, sMemberType, sMemberName, 1 If (sMemberType = "=") { iMemberType := COM_PROPPUT StringTrimRight, sMemberName, sMemberName, 1 } Else { iMemberType := COM_PROPGET } } Return iMemberType } __GetExceptionInfo() { global EASYCOM_DLL SetFormat, Integer, H sMsg := "Code: " DllCall(EASYCOM_DLL . "\GetException_Code", "uint") SetFormat, Integer, D If (DllCall(EASYCOM_DLL . "\GetException_Source") <> 0) sMsg := sMsg . "`n" . "Source: " . DllCall(EASYCOM_DLL . "\GetException_Source", "str") If (DllCall(EASYCOM_DLL . "\GetException_Description") <> 0) sMsg := sMsg . "`n" . "Description: " . DllCall(EASYCOM_DLL . "\GetException_Description", "str") If (DllCall(EASYCOM_DLL . "\GetException_HelpFile") <> 0) sMsg := sMsg . "`n" . "Help File: " . DllCall(EASYCOM_DLL . "\GetException_HelpFile", "str") iHelpCtx := DllCall(EASYCOM_DLL . "\GetException_HelpContext") If (iHelpCtx <> 0) sMsg := sMsg . "`n" . "Help Context: " Return sMsg } __COMTypeToAHKType(iType) { global COM_VOID ,COM_SKIP ,COM_INT ,COM_FLT ,COM_DBL ,COM_STR ,COM_OBJ ,COM_OBJ_UNKN ,COM_ARRAY ,COM_VARIANT ,COM_BYREF If (iType = COM_SKIP) Return "int" Else If (iType = COM_INT) Return "int" Else If (iType = COM_FLT) Return "float" Else If (iType = COM_DBL) Return "double" Else If (iType = COM_STR) Return "str" Else If (iType = COM_OBJ) Return "int" Else If (iType = COM_OBJ_UNKN) Return "int" Else If (iType = COM_ARRAY) Return "int" ;Else If (iType = COM_VARIANT) ; Under development ; Return "str" Else Return } __COMRetToAHKType(iType) { global COM_STR sType := __COMTypeToAHKType(iType) If (iType = COM_STR) Return sType Else Return sType . "p" }