The SDK is a collection of tools and libraries which enable the DCOM developer to build DCOM applications.
This document covers the following topics:
The following differences between DOS and UNIX command syntax apply in general when using a utility with command-line input:
| DOS | UNIX | |
|---|---|---|
| Command switch | / | - |
| Input redirection | @ | (unavailable) |
| Command arguments | midl -? | midl -\? |
The command switch / (slash) is permitted on UNIX but its use is not recommended. Use "-" (hyphen) instead.
All command arguments have to follow the UNIX shell rules (i.e. quoting, escape characters, wildcards, regular expressions). For example, midl -? does not work with the C shell, so you have to use midl -\? or midl -? (Bourne-compatible shells do not have this problem).
This is the uuidgen utility from Windows with some enhancements to implement functionality found in the guidgen graphical Windows utility.
For more information on how to use uuidgen please consult the Microsoft documentation: RPC Programmer's Guide and Reference - MS Win32 Software Development Kit. Alternatively, look at the online documentation that comes with the MS C/C++ Compiler in the MS Developer Studio. OSF/DCE supply a version of uuidgen, so be sure to use the correct one.
The uuidgen utility (or rather, the RPC library function which uses it) looks up the registry for the MAC (Medium Access Control) address of your NIC (network interface card) as an input parameter for the UID generation. If there is no information in the registry, the uuidgen utility will try to get the hardware address information at runtime and then insert it into the registry automatically for permanent use.
General help information can be found in the uuidgen help pages (activated by uuidgen -help) and the existing Microsoft documentation for uuidgen.
The EntireX DCOM uuidgen utility is based on version 1.00 of uuidgen on
Windows. EntireX DCOM specific version information is available in the
signature (i.e. with uuidgen -v).
In EntireX DCOM, guidgen is an extension to the uuidgen utility. In effect, guidgen is a copy of the uuidgen utility. It is provided for convenience since most people use this utility instead of uuidgen.
For more information on how to use guidgen, consult the Microsoft documentation: RPC Programmer's Guide and Reference - MS Win32 Software Development Kit. Alternatively, look at the online documentation that comes with the MS C/C++ Compiler in the MS Developer Studio.
EntireX DCOM's version of the guidgen utility is based on the version
1.00 of uuidgen on Windows. EntireX DCOM specific version information is
available in the signature (i.e. with uuidgen -v).
The makedef utility is a Bourne shell script provided to compile Windows specific ".def" files. The utility generates a C++ module that has to be compiled and linked into your shared library in order to make it loadable using the Windows LoadLibrary() and GetProcAddress() functions. You can use C preprocessor statements (e.g. #include, #if, #ifdef, #else, #endif) to make makedef conditionally parse blocks of the DEF file.
Usage:
makedef [-RCTAB] [-D<string>] [-U<string>] [-E<entrypoint>] [-I<includepath>] def_file output_file
Parameters:
-RCTAB: If you want to compile a message file
into your shared library, you also need a .def file.
-RCTAB is used to tell makedef to include a global
symbol, the resource table generated by the tool coolmc (described below), into your share
library.
-D<string>: Use
-D to specify a string that will be passed as
conditional compile flag to the preprocessor by the makedef utility.
-U<string>: Use
-U to undefine a flag for the preprocessor.
-E<entrypoint>: Use
-E to define the main entry point function into your
shared library. This function will be called in order to initialize the shared
library after loading.
-I<includepath>: Use
-I to define an additional directory where your include
files can be found.
def_file: Path and name of the DEF file to process.
output_file: Path and name of the output file to be created (by default it is <file_name>_def.cxx).
EntireX DCOM provides an implementation of the Microsoft Interface Definition Language compiler MIDL. Refer to the Microsoft documentation: RPC Programmer's Guide and Reference - MS Win32 Software Development Kit for a full description of MIDL. To avoid duplication, only a brief summary is provided here. Alternatively, look at the online documentation that comes with the MS C/C++ Compiler in the MS Developer Studio.
Temporary files are created with the tmpnam() standard library function. Refer to your manual page for tmpnam() to get information on the directory used for temporary files. Names of temporary files start with MID. They are removed automatically by MIDL after compilation.
There are no specific error codes, other than the ones documented by Microsoft.
Help information can be found in the midl help pages (activated by midl -help) and the existing Microsoft documentation for MIDL.
Sample IDL files are delivered with the EntireX DCOM SDK.
There is no dependency on the registry that is provided with EntireX DCOM.
The EntireX DCOM implementation of MIDL is based on the version 5.03.0279 of MIDL on Windows. EntireX DCOM-specific version information is available in the signature.
This is a type library generation tool for automation. The EntireX DCOM version of mktyplib is based on version 2.0.0 of mktyplib on Windows. EntireX DCOM-specific version information is available in the signature.
There are no error codes specific to EntireX DCOM, other than the ones documented by Microsoft.
Help information can be found in the mktyplib help page (activated by
mktyplib -help) and existing Microsoft documentation for
mktyplib.
Coolmc is the EntireX DCOM version of the Windows mc (message compiler) utility. It is used to compile message files containing application-specific messages which can be retrieved from the application by calling a WIN 32 API. Currently, coolmc supports only one language, English.
The syntax of the message file must follow the rules as it does for Windows.
Usage:
coolmc <message-file>
, e.g. coolmc xyz.mc
This call to coolmc will produce three output files xyz.rc, xyz.h and a binary file with the extension ".bin" (the file name is generated according to the rules on Windows systems).
The file xyz.h will contain macros which define the error number as hexadecimal values (generation of decimal error numbers is not supported).
The file xyz.rc only contains the name of the binary file plus the language definition.
The binary file *.bin contains the message table in an internal, binary format.
The header file xyz.h can be included in your source code to provide the application with the macros for the messages.
If you already have a resource file in your application, include the xyz.rc file in that resource file.
If you do not have any resource file, add the following two lines to your makefile:
$(OBJDIR)/xyz_rc.cxx: xyz.rc makerc $(C_DEFINES) $(C_INCLUDES) xyz.rc $@
and add xyz_rc.cxx to the list of files to be compiled for your application.
To be able to retrieve messages from a shared library, you must use a
".def" file for the shared library. See the description of
makedef, above. You need an additional
parameter, -RCTAB, for the makedef call.
In your application you can retrieve these messages using the FormatMessage API.
The SDK contains a set of header files (Microsoft headers ported to non-Windows platforms as well as headers provided by Software AG) for inclusion in source files for compilation. The header files are located in the directory $EXXDIR/$EXXVERS/sdk/include.
This kit includes an implementation of the Microsoft Active Template Library (ATL) version 3.0. The ATL version provided does not support default template arguments, because these are not supported by the compilers available on the EntireX DCOM platforms.
ATL servers generated by the Microsoft Developer Studio's AppWizard will
use calls to GetMessage(),
DispatchMessage() and
PostQuitMessage() to control the lifetime of the
server. EntireX DCOM supports only restricted versions of these Windows API
calls. Alternatively, you can use a Win32 Event to signal process shutdown.
Refer to the ATL Program Porting Guide for a description of how to port Active Template Library (ATL) applications from Windows to EntireX DCOM platforms.
It is sometimes undesirable when COM objects maintaining resources which are expensive to create, are shut down as soon as there are no more references to that object. Providing an object pool holding ready-to-use objects for clients to retrieve and put back, and keeping them alive over a period of idleness improves this situation.
The component object pool provides the following services to client applications:
creates a new object and returns an IUnknown interface pointer to the client application if there is no free object of the requested class available in the pool.
returns an IUnknown interface pointer of an existing and free object to the client application.
keeps unused objects in the pool for a period of idle time.
shuts down unused objects from the pool if their maximum idle time is exhausted.
The object pool is delivered as an executable objpool and a type library objpool.tlb and is installed into the EntireX binary directory. Before it is used for the first time, the object pool needs to be registered with:
$ objpool -RegServer
The object pool is normally a long-running task. It should thus be started as a daemon, either using the daemon starter utility ntwopper:
$ ntwopper -nowait objpool
or by adding it to the list of processes to be started up automatically by the ntd daemon (see COOL_NTD_INIT_COMMAND and COOL_NTD_INIT_START in the dcomconfig file.)
When no object pool instance is running and a client application creates one, the object pool terminates as soon as there are no more objects kept alive in the pool.
The object pool can be unregistered with:
$ objpool -UnregServer.
The object pooling object provides a dual interface (both dispatch and vtable) interface IObjPool which contains methods to:
create a new object (or retrieve an existing free object) from the pool
release (give back) a previously created object and mark it as free in the pool
add an object (which has been created by the object pooling object) to the pool
configure a maximum idle time for a given object in the pool.
| Method | Description | Parameters | Return Codes | ||||||
|---|---|---|---|---|---|---|---|---|---|
CreateObject HRESULT CreateObject( [in] BSTR wszClsid, [out] LONG *dwReg [out, retval] IUnknown **pUnk, ); |
Creates an object in the pool or returns an interface pointer to an existing, free object. |
|
CreateObject uses CoCreateInstanceEx to create new objects. If this function fails, CreateObject passes the errorcode returned to the caller. | ||||||
ReleaseObject HRESULT ReleaseObject( [in] LONG dwReg ); |
Releases an object previously created in the pool (marks it as unused). |
|
If the object identified by dwReg cannot be found in the pool, E_FAIL is returned. | ||||||
AddObject HRESULT AddObject( [in] BSTR wszClsid, [in] IUnknown *pUnk, [out] LONG *dwReg ); |
Adds an object created by the caller to the pool. |
|
|||||||
SetIdleMax HRESULT SetIdleMax( [in] LONG dwReg, [in] LONG maxIdleCount ); |
Sets the maximum idle period of an object in the pool. |
|
|||||||
Status HRESULT Status( [in, out] BSTR * bstrBuffer ); |
Requests that the server print the status of the pool. |
|
The current implementation of the object-pooling object has some limitations:
Clients which retrieve objects from the object pool (using CreateObject) have to return the object (using ReleaseObject) to the pool. The object pool does not check whether a client is still alive, thus objects are kept busy for the lifetime of the object pool if clients do not return their objects correctly (either because of programming errors or because of crashes).
The object pool does not check whether a client requesting an object from the pool is authorized to access this object. The object pool hands the interface of a free (or newly created) object to the client. If the client is not authorized to access the object, it will receive an error from the object.
| proxy: | The Interface description of the server. Used to generate a type library. |
| client: | A Test client. Uses the clerksrv example server for testing. |
To build
Change to $EXXDIR/$EXXVERS/examples/dcom/objpool
$ make
To register the objpool server
$ objpool -RegServer
To run the example client
Build and register $EXXDIR/$EXXVERS/examples/dcom/rental
$ objpoolcl
The following sections provide a brief description of compiling and linking EntireX DCOM applications. The flag settings for the C and C++ compilers for compiling and linking DCOM applications, together with the flag settings necessary for running the MIDL compiler, are in the central makefile in $EXXDIR/$EXXVERS/sdk/samples/make/makefile.incl.
Please refer to the distribution kit for examples of how to build DCOM applications.
There are two mandatory preprocessor symbols which must be defined to the C, C++ and MIDL compilers in order to build EntireX DCOM applications correctly. These symbols are
SAG_COM, and
A symbol identifying the target platform:
| Platform | Value |
|---|---|
| AIX | CE_TAIX |
| HP-UX (32 bit) | CE_THP9000S800 |
| HP-UX (64 bit) | CE_THPUX11_64 |
| Sun Solaris (32 bit) | CE_TSUNSOL2 |
| Sun Solaris (64 bit) | CE_TSUNSOL7_64 |
| Linux | CE_TLINUX86 |
| Linux IA64 (64 bit) | CE_TLINUXIA64 |
For the complete list of the flag settings, please refer to makefile.incl and the sample makefiles.
DEF (shared library definition) files are processed with the makedef utility, which generates C++ files. See the description of the makedef utility in the section SDK Tools above. The C++ files are then compiled to produce .o files, which are then linked to create DLLs (called shared libraries on UNIX systems). The DLLs created on UNIX systems export all symbols (on Windows systems, the symbols in a DLL can be exported selectively).
To generate a proxy/stub library
Write an IDL file which specifies the object and interfaces.
Write a DEF file specifying the library's name which exports at least DLLRegisterServer, DllUnregisterServer, DllCanUnloadNow, DllGetClassObject.
Ensure that the name of the DLL as specified in the DEF file for LIBRARY is the same as the base name of the DLL itself. Thus, for example, if you specify "LIBRARY footest", the library must be named libfootest.so.
Run midl on the IDL file to generate the header, *_i.c, *_p.c and dlldata.c files.
Compile the MIDL-generated C files (and additional ones if present).
Make sure that -DREGISTER_PROXY_DLL and -DCOBJMACROS preprocessor definitions are passed to the compiler when compiling the generated C files.
Link the generated objects to the proxy stub DLL (together with the additional link libraries ole32 and rpcrt4).
Register the generated proxy stub DLL by executing regsvr
<path>/<libname>.
Refer to the MIDL sections in this documentation and to Microsoft's documentation for details on using the MIDL compiler.
For more detailed information see also Michael Nelson's article Using Distributed COM with Firewalls, at: http://www.microsoft.com/com/wpaper/dcomfw.asp.
DCOM clients must be able to reach the DCOM server at its actual IP address. It is not possible to access the DCOM server through firewalls that translate the network address. This is due to the fact that the IP address of the server machine is stored in the marshalling packets, which is used by the client to establish a TCP/IP connection.
To enable DCOM to send out the translated Network Address within the marshalling packets to remote DCOM clients, make the following entries in the server machine's registry.
Create the registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Software AG\EntireX\DCOM\NetworkAddressTranslation
with a MULTI_SZ value named "TranslationList" and define as value the IP address behind (intranet) and in front of (internet) the firewall separated by an equal sign. These settings must correspond to the network address translation of the firewall system.
Example:
If the server IP address behind the firewall were 192.25.192.1 and in front of the firewall 199.166.2.10, the MULTI_SZ values in hex ASCII would be
REGEDIT4 [HKEY_LOCAL_MACHINE\SOFTWARE\Software AG\DCOM\NetworkAddressTranslation] "TranslationList"=hex(7):31,39,32,2e,32,35,2e,31,39,32,2e,31,3d,\ 31,39,39,2e,31,36,36,2e,32,2e,31,30,00,00
In contrast to other internet applications, by default DCOM dynamically assigns TCP ports in a range between 1024 and 65535. For security reasons firewall systems are usually configured to restrict the range of ports available. Thus, the port range of DCOM must be restricted as well. This is done with the following registry settings:
Create a registry key:
HKEY_LOCAL_MACHINE\Software\Microsoft\Rpc\Internet
| with the values: | REG_MULTI_SZ | Ports | one port range per line |
| REG_SZ | PortsInternetAvailable | always set to Y | |
| REG_SZ | UseInternetPorts | Y | N |
Example:
Restrict the DCOM port range to the ports 7778 and 7779 (the MULTI_SZ values are given in hex ASCII below).
REGEDIT4 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Rpc\Internet] "Ports"=hex(7):37,37,37,38,00,37,37,37,39,00,00,00 "PortsInternetAvailable"="Y" "UseInternetPorts"="Y"
DCOM Applications need to perform some basic initialization steps for the WIN32 subsystem (Windows daemon ntd and mutant library) before using any WIN32 APIs. This initialization can be achieved in two ways:
Using CoolMain()
Using your own main() function
Use CoolMain() as the application's main
function, in which case the real main() function is
taken from the libmutantstubs.a library. This default
main() function performs all the necessary
initializations, calls CoolMain() and when this
function returns, performs all of the necessary de-initializations.
Example:
#ifdef SAG_COM
#include <coolmain.h>
int CoolMain(int argc, char *argv, char **envp)
#else
int main(int argc, char *argv, char **envp)
#endif
{
...
}
Define a main() function of your own which
initializes the WIN32 subsystem prior to calling any WIN32 APIs by calling
CoolMainInit(); de-initialize it by calling
CoolMainExit() before returning from
main().
Example:
#ifdef SAG_COM
#include <coolmain.h>
#endif
int main(int argc, char *argv, char **envp)
{
#ifdef SAG_COM
CoolMainInit(argc, argv, envp);
#endif
...
#ifdef SAG_COM
CoolMainExit();
#endif
return ...;
}
The default makefile template $EXXDIR/$EXXVERS/include/makefile.incl delivered with the EntireX DCOM SDK uses the C++ Compiler driver to link DCOM binaries (executables as well as shared libraries). If no C++ compiler is installed on your system, it is still possible to build and link DCOM applications by using the C compiler driver even though the DCOM libraries are built with the C++ compiler. The C++ runtime libraries must be added to the list of link libraries.
Note:
The following restrictions apply under HP-UX 11 32-bit
The C compiler driver cc cannot link shared libraries. If you wish to link shared libraries without the C++ compiler driver aCC, then the linker ld must be used with the proper options (please consult the vendor's documentation for cc and ld).
The C compiler driver cc is able to link executables with the following restrictions:
If object (.o) files which have been built with the C++ compiler are linked into the executable, and these objects have global class instances, the constructors and destructors of these instances will not fire.
In order for constructors/destructors of global class instances in
shared libraries which are loaded by the executable to fire, the function
_main() (provided by HP-UX) must first be called once.
The default main() function provided by EntireX DCOM
calls _main() before calling the DCOM application's
CoolMain(). The function
_main() is also called by the initialization function
CoolMainInit().