:Start of DirectIfaceCall
![]() | ![]() |
|---|
If you are viewing this script in your browser you can save it as a VDS 5.x source file (*.dsc) to run it.
# # DragonSphere Software's Home Page # # All Source Files for this demo Title Direct Object Access Example ################################################ DESCRIPTION ################################################# # # # This is a very advanced example # # The technics demostrated in this example should only be used by an experienced COM developer # # # # This example demostrates the use of # # @Ole(CreateEx) and @CallFuncPtr() functions to access COM object interfaces directly. # # # # How to start using COM or ActiveX interfaces directly? # # You start using them by first defining the Interface. # # Note: This has changed from my first version. Interfaces are now unique high level data types in # # GadgetX. So Interfaces are now treated different from Structures or Records in the way that # # GadgetX handles the memory allocation and de-allocation of interfaces. # # Basicly the Define Interface command allows GadgetX to know how to find the addresses of the methods # # in a COM or ActiveX object without the need of a TypeLibrary or IDispatch as in the OLE commands # # and functions. The OLE commands and functions are just wrappers around the IDispatch interface and # # require the IDispatch interface in most cases for them to work. # # The reasons for not using a TypeLibrary or the IDispatch interface is that not all objects have these # # and they are not required. As a matter of fact the only interface that is required is the IUnknown # # interface and is defined in the example below. # # Warning: When defining a Interface the order and number of method names are VERY important!!! # # Use a tool like the GadgetX TLibInfo Browser or Microsoft's OleView to get the order and names # # of the methods, properties, and parameter types. # # Second you call the @Ole(CreateEx) function and pass the needed parameters for the Object you want to # # use. You can think of @Ole(CreateEx) as a fancy combined function in place of Gadget's @LoadDLL() and # # @GetFuncPtr() specifically made for loading COM/ActiveX components/objects into memory instead of just # # DLLs. # # Now you can start calling methods like you would any Win32 API function with the @CallFuncPtr() function # # passing the required parameters. # # Note: Since this is such a low level way of calling COM/ActiveX objects you must do reference counting. # # The @CallFuncPtr() is a lov level multi-purpose function for calling generic function addresses # # and will not know to automaticly call the AddRef and Release methods on an object. Unlike the use # # of SmartPointers found in languages such as C++. # # # # Using the techniques described in this example allows you to use any COM or ActiveX interface as long # # as you know the names of the methods (ie...Functions), calling convetion, number and usage of parameters # # of the methods, and the return type of the method. This makes calling these methods very quick and to # # the point. The overhead is closer to that of languages such as C/C++ for calling COM objects with the # # exception that you are defining and using the objects interface at runtime instead of at compile time. # # Note About Properties: Properties are usually a variable in the object and there is always a method # # that returns or sets the properties value so you would place the name of the # # COM method that returns or sets the properties in the proper order. Most likely # # these methods have the words get_ and set_ prefixed in the method names that # # deal with that property as is the case for Internet Explorer's ActiveX interfaces. # # # ############################################################################################################## If @Greater(@Name(@SYSINFO(DSVER)),4) External GadgetX.dll,@SYSINFO(DSVER) # GadgetX Commands needed for this example #DEFINE COMMAND,GadgetX,DEFINE,OLE,INTERFACE,Set,FREEDLL,CALL,MEM # GadgetX Functions needed for this example #DEFINE FUNCTION,GadgetX,OLE,INTERFACE,Get,ADDROF,SIZEOF,GETLASTERROR,LOADDLL,CALL,OR,AND,GETFUNCPTR,CALLFUNCPTR,MEM Else Warn This Example uses VDS 5 or above syntax. End # Enum CLSCTX Define Constant,CLSCTX_INPROC_SERVER,$1 Define Constant,CLSCTX_INPROC_HANDLER,$2 Define Constant,CLSCTX_LOCAL_SERVER,$4 Define Constant,CLSCTX_INPROC_SERVER16,$8 Define Constant,CLSCTX_REMOTE_SERVER,$10 Define Constant,CLSCTX_INPROC_HANDLER16,$20 Define Constant,CLSCTX_RESERVED1,$40 Define Constant,CLSCTX_RESERVED2,$80 Define Constant,CLSCTX_RESERVED3,$100 Define Constant,CLSCTX_RESERVED4,$200 Define Constant,CLSCTX_NO_CODE_DOWNLOAD,$400 Define Constant,CLSCTX_RESERVED5,$800 Define Constant,CLSCTX_NO_CUSTOM_MARSHAL,$1000 Define Constant,CLSCTX_ENABLE_CODE_DOWNLOAD,$2000 Define Constant,CLSCTX_NO_FAILURE_LOG,$4000 Define Constant,CLSCTX_DISABLE_AAA,$8000 Define Constant,CLSCTX_ENABLE_AAA,$10000 Define Constant,CLSCTX_FROM_DEFAULT_CONTEXT,$20000 Define Constant,CLSCTX_ACTIVATE_32_BIT_SERVER,$40000 Define Constant,CLSCTX_ACTIVATE_64_BIT_SERVER,$80000 # default LCID's which most COM interfaces rely on to display and read variables # in their proper languages. Define Constant,LOCALE_SYSTEM_DEFAULT,$800 Define Constant,LOCALE_USER_DEFAULT,$400 # Usually if the method works it will return the HRESULT $00000000 or a error value Define Constant,S_OK,$00000000 # GUID = UUID = IID = CLSID = Interface ID's # All these names have the same meaning to GadgetX so treat them the same. # GadgetX defines these as a 16 byte structures defined as follows # Define Structure,GUID,DWORD|Data1,WORD|Data2,WORD|Data3,BYTE|Data4[8] # Lucky for all of us I have built a wrapper for this. # Most Methods and functions need a pointer to the GUID # So if you use @AddrOf() you can get the pointer address. # COM Interface ID's can be found in the following Registry keys. # HKEY_CLASSES_ROOT\CLSID # HKEY_CLASSES_ROOT\Interface Define IID,IID_NULL,{00000000-0000-0000-0000-000000000000} Define IID,IID_IUnknown,{00000000-0000-0000-C000-000000000046} Define IID,IID_IDispatch,{00020400-0000-0000-C000-000000000046} # Pointer variable we will use to hold the Address of a IID Define Variable,Pointer,piid # # Syntax: Define Interface, , ,<...> # # Example: Define Interface,IUnknown,QueryInterface,AddRef,Release # NOTE: All Interfaces require the IUnknown interface as their first 3 methods. # I may change GadgetX later to automaticly detect if you defined these or not. Define Interface,IDispatch,QueryInterface,AddRef,Release Interface Add,IDispatch,GetTypeInfoCount,GetTypeInfo,GetIDsOfNames,Invoke # The astric '*' in front of the Pointer variable type tells the @CallFuncPtr function # to assign the value of the returned argument to the address of the argument. A pointer variable without # the astric '*' will assign the address of the returned argument to the value of the returned argument. # This variable type will not work with any other GadgetX command or function. # This is only needed when passing a pointer to a pointer of a interface as # in the QueryInterface method. # Note: You must use a GadgetX variable for this to work since GadgetX treats Interfaces as special Define Variable,*Pointer,punk Define Variable,*Pointer,disp # Worker variables to hold various data # bstrMember will hold the memory address of a BSTR/OLESTR Define Variable,Pointer,bstrMember # pbstrMember will hold the memory address of bstrMember Define Variable,Pointer,pbstrMember # dispid will hold the value of the Dispatch ID Define Variable,Long,dispid # pdispid will hold the memory address of dispid Define Variable,Pointer,pdispid # Ok we are done with all the definitions now lets have some fun ;) # Always remember to Initialize Ole before you try to use it. Ole Init # save the Address of IID_IDispatch Interface ID to the piid pointer set piid,@AddrOf(IID_IDispatch) # Use the CreateEx wrapper function to create a new instance of a COM Interface # and get a pointer to that COM interface. This wrapper function is not needed but # you have to agree it is much easier than using all the functions and methods that would be required # Syntax: # = @Ole(CreateEx, , , , , , ) Set disp,@Ole(CreateEx,InternetExplorer.Application,IID_IDispatch,CLSCTX_LOCAL_SERVER,NULL,NULL,IDispatch) # Now we can use the interface and call any method by name in this case we are requesting the IDispatch interface # With the advent of the # REMEMBER: Normally you would need to pass the interface pointer as the first argument of each method called. # Most languages hide the interface pointer like the C++ pre-compilier and it's use of the thiscall. # Since this is a common practice and it looks better I made this possible with the @CallFuncPtr function. # The first version of this function could not do this. There is some differences between using the @CallFuncPtr # and other languages. Bellow is an example of the differences especially when # calling the QueryInterface method. # Note: There is really no need to call the AddRef method after @Ole(CreateEx) # is called since @Ole(CreateEx) does this for you. In most cases as long as you call the Release method # for every AddRef method that is called most objects will allow you to do this. %%RefCount = @CallFuncPtr(STANDARDMETHOD,DWORD,IDispatch.AddRef) Info Reference count = %%RefCount # Initialize the dispid to a value Set dispid,0 # Save the address of dispid to the pdispid pointer Set pdispid,@AddrOf(dispid) # Set piid to the Address of IID_NULL set piid,@AddrOf(IID_NULL) # This can be any valid Method name that is part of this interface # Most IDispatch interfaces are what is called a aggregate of the IDispatch interface # and some other interface. This means that the object appends another interface to the end # of the IDispatch interface and treats it as a new unique interface. Like I said before you # do not need to use the IDispatch interface at all if you know the names of all the methods. # See Also: GadgetX TLibInfo Browser to get the names of the methods and properties. # Note About Properties: Properties are usually a variable in the object and there is always a method # that returns or sets the properties value. %%MethodName = Visible # Save a method's name as a BSTR or OLESTR and assign the Address to the bstrMember pointer Set bstrMember,@Ole(VdsToBstr,%%MethodName) Set pbstrMember,@AddrOf(bstrMember) # We have everything we need to call the GetIDsOfNames Method # Notice that we are returning a HRESULT # A HRESULT is just a Long variable type represented as a # Hex value base 16 instead of a decimal value base 10. # I don't know why the VDS function @Hex function does not append a $ token character # in front of the number but it does not so to use Hex numbers with other # VDS math function I gave GadgetX the ability to return the Long type as a # hex number. GadgetX fully reconizes the token $ character in all numeric # cases and will convert the numbers as nessassary. %%HResult = @CallFuncPtr(STANDARDMETHOD,HRESULT,IDispatch.GetIDsOfNames,piid,pbstrMember,Integer|1,DWORD|@Get(LOCALE_SYSTEM_DEFAULT),pdispid) If @Equal(%%HResult,@Get(S_OK)) # If everything went well we should see the DISPID 402 here. Info The Method @Ole(BstrToVds,bstrMember) has a DispID of @Get(dispid) Else # If something went wrong show the error code with will be in %%HResult as a # hex number. You can look up these error codes in the objects documentation. # If this is a Mircorsoft Object you should be able to get the errorcode meaning # at MSDN Warn Method returned errorcode %%HResult End # Get the Address of the IUnknown Interface ID Set piid,@AddrOf(IID_IUnknown) # Setup the Pointer to Pointer variable # This is really just to give punk a value of # the correct size and shape. The IUnknown interface # does not need to be initialized but the punk variable requires # initialization. # The name punk is shorthand for "pointer to IUnknown" # GadgetX does not allocate any memory for a variable until you # use that variable with the exception of Structures, Records, and Interfaces. # Assign the Address of the IUnknown Interface to the punk variable to give punk # the proper meaning. Set punk,@AddrOf(IUnknown) # Call the IDispatch QueryInterface method to get a pointer to the IUnknown interface # Notice that we are returning a HRESULT # A HRESULT is just a Long variable type represented as a Hex value. %%HResult = @CallFuncPtr(STANDARDMETHOD,HRESULT,IDispatch.QueryInterface,piid,punk) If @Equal(%%HResult,@Get(S_OK)) # If everything is ok we can now get the Interface that is held in the # punk Pointer to Pointer variable # We will now save the Interface back into the IUnknown structure # so we can call the Interface Methods by name instead of using the # memory addresses and offsets which is a real pain but it can be done # but why bother let GadgetX do all these calculations for you. Set IUnknown,@Get(punk) # Now we can call the AddRef method and any other method in this interface just # like any Win32 API function. %%RefCount = @CallFuncPtr(STANDARDMETHOD,DWORD,IUnknown.AddRef) Info Reference count = %%RefCount # Next we have examples of how to use some of the Gadgetx OLE commands/functions with # these interfaces. # Get the TypeInfo for the Object # This GadgetX function can use any interface since it only # requires an initial IUnknown interface to start with. # NOTE: All Interfaces include the IUnknown interface as the first 3 methods but not # all interfaces have TypeInfo associated with them. %%TypeInfo = @Ole(GetControl,TypeInfo,IUnknown) # Display the Objects TypeInfo if available. If %%TypeInfo Info %%TypeInfo@CR() Else Warn This object does not have any Type Information associated with it. End # Clean the %%TypeInfo variable since it uses alot of memory. %%TypeInfo = # We are finished using IUnknown so Release the reference to it. %%RefCount = @CallFuncPtr(STANDARDMETHOD,DWORD,IUnknown.Release) Info Reference count = %%RefCount Else # If something went wrong show the error code with will be in %%HResult as a # hex number. You can look up these error codes in the objects documentation. # If this is a Mircorsoft Object you should be able to get the errorcode meaning # at MSDN Warn Method returned errorcode %%HResult End # Since IDispatch now points to a Dispatch interface # we can use any of GadgetX's Ole wrapper commands and functions. Ole Set,IDispatch,"Visible = ^B",True Ole Call,IDispatch,"Navigate(^B)",http://www.dragonsphere.net wait Info Now VDS has the best of both worlds.@CR()We can use the Simple IDispatch Ole wrappers@CR()or any other COM interface with a little work. # Start the clean up process # The Internet Explorer Application object requires that you call it's Quit method # before closing. Ole Call,IDispatch,Quit # Release all references to the Object. While @Greater(%%RefCount,0) # Release while the Reference count is greater than 0 %%RefCount = @CallFuncPtr(STANDARDMETHOD,DWORD,IUnknown.Release) Info Reference count = %%RefCount@CR() Wend # UnInitialize Ole Ole UnInit Exit
© Copyright DragonSphere Software 2000-2005
Terms and Conditions