Document revision date: 15 July 2002
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

COM, Registry, and Events for OpenVMS Developer's Guide


Previous Contents Index


Chapter 7
Developing a COM for OpenVMS Application

This chapter explains how to develop COM applications for OpenVMS.

Note

You can find the sample COM applications shown in this chapter in the following directories on the COM for OpenVMS kit:


DCOM$EXAMPLES:[SAMPLE1] 
DCOM$EXAMPLES:[SIMPLE] 
DCOM$EXAMPLES:[DISPATCH_SAMPLE1] 

SAMPLE1 and DISPATCH_SAMPLE1 are taken from Dale Rogerson's book, Inside COM, published by Microsoft Press. This book is a good reference for developing COM applications.

The following sections describe how to create a COM for OpenVMS application.

Note

Building COM for OpenVMS applications places demands on the virtual memory requirements of a process. You should have a minimum page file quota of 100,000 pagelets before building a COM for OpenVMS application. This is a Compaq C++ compiler requirement.

7.1 Step 1: Generate Unique Identifiers

Use the DCOM$GUIDGEN utility to generate 16-byte globally unique identifiers (GUIDs). The utility supports both OpenVMS and UNIX styles. For example:

The following table summarizes the GUID format options.
OpenVMS qualifier (value) UNIX switch Use
IDL -i Output GUID in an IDL interface template.
STRUCT -s Output GUID as an initialized C struct.
IMPLEMENT_OLECREATE -c Output GUID in IMPLEMENT_OLECREATE(...) format.
DEFINE_GUID -d Output GUID in DEFINE_GUID(...) format.
GUID_STRUCT -g Output GUID as an initialized static const GUID struct.
REGISTRY_GUID -r Output GUID in registry format.

Note

The last four options in the preceding table are the same as the four options in the Windows NT Guidgen utility.

The following table lists additional options supported by the DCOM$GUIDGEN utility.
OpenVMS qualifier UNIX switch Use
/OUTPUT= filename -o filename Redirect output to a specified file.
/COUNT= number -n number Number of GUIDs to generate.
not available -h , -? Display command option summary.

You can specify more than one format for the same GUID.

7.2 Step 2: Build an Application Using the MIDL Compiler

The following sections describe how to use the MIDL compiler to build an application.

7.2.1 Running the MIDL Compiler

The MIDL compiler consists of the following separate images:

To run MIDL, you must first define a DCL symbol. For example:


    $ midl :== $dcom$midl 
    $ midl -? 
    $ midl -Oicf -idcom$library: example.idl 

The midl -? command displays a list of valid command-line arguments. For a list of these arguments, see Appendix A.

7.2.2 Running the MIDL Compiler with DCOM$RUNSHRLIB

The DCOM$MIDL.EXE utility gets its arguments from the DCL foreign command-line buffer. DCL foreign commands can have a maximum of 255 characters.

Because of the number of arguments that DCOM$MIDL.EXE can accept, you might exceed this maximum number of characters if you specify a complex MIDL command (for example, a command that contains mixed-case arguments that require quotation marks).

As a workaround, you can use the SYS$SYSTEM:DCOM$RUNSHRLIB.EXE utility. Use the following procedure:

  1. Define the DCL command DCOM$RUNSHRLIB .
    A process that needs to use DCOM$RUNSHRLIB.EXE must first use the OpenVMS DCL Command Definition utility to define the DCL command DCOM$RUNSHRLIB . For example:


      $ SET COMMAND DCOM$LIBRARY:DCOM$RUNSHRLIB.CLD 
    

    DCOM$LIBRARY:DCOM$RUNSHRLIB.CLD defines the DCOM$RUNSHRLIB DCL command. The following table shows the command's parameters.
    Argument Value Required/Optional
    P1 Name of the shareable image library. This can be a logical name, the name of an image in SYS$SHARE: , or a full file specification. Required
    P2 Name of the routine to be called as a C or C++ main() routine with an argc/argv vector. Required
    P3 List of qualifiers, in quotation marks. Optional

  2. Define the DCL symbol midl to use DCOM$RUNSHRLIB.EXE to parse the command line and call the DCOM$MIDL_MAIN function in the DCOM$MIDL_SHR shareable image library. For example:


      $ midl :== DCOM$RUNSHRLIB DCOM$MIDL_SHR DCOM$MIDL_MAIN 
    

    The new DCL command MIDL accepts multiple command-line arguments inside a single quoted string. If the command becomes too long, you can specify multiple quoted strings, using a comma to separate the strings.
    For example, here is a complex MIDL command that fails:


      $ midl :== $dcom$midl 
      $ midl -Zp8 -Oicf -Os -oldnames -char unsigned - 
         -error allocation -error bounds_check -error stub_data - 
         -ms_ext -c_ext -out [.OBJ] - 
         -I[INC] -I[PROJECT_WIDE_INC] -I[COMMON_INC] -IDCOM$LIBRARY: - 
         -DRMS_DB "-DOpenVMS_Definitions" "-DPermanentProcess" - 
         -header [.obj]example.h -client none -server none example.idl 
      %DCL-W-TKNOVF, command element is too long - shorten 
    

    You can successfully specify this command using DCOM$RUNSHRLIB as follows:


      $ set command dcom$library:dcom$runshrlib.cld 
      $ midl :== DCOM$RUNSHRLIB DCOM$MIDL_SHR DCOM$MIDL_MAIN 
      $ midl "-Zp8 -Oicf -Os -oldnames -char unsigned",- 
         "-error allocation -error bounds_check -error stub_data",- 
         "-ms_ext -c_ext -out [.OBJ]",- 
         "-I[INC] -I[PROJECT_WIDE_INC] -I[COMMON_INC] -IDCOM$LIBRARY:",- 
         "-DRMS_DB -DOpenVMS_Definitions -DPermanentProcess",- 
         "-header [.obj]example.h -client none -server none example.idl" 
    

7.2.3 Modifying Your Applications To Use the C++ Only MIDL Compiler

By default, the MIDL compiler included in COM Version 1.2 for OpenVMS generates IDL files with a .CXX extension. If you previously specified names for the generated files in your MIDL command and want to use the COM Version 1.2 for OpenVMS MIDL compiler changes, you need to update your command line.

For example, if you previously generated IDL files with the following command:


  MIDL -Oicf server.idl -IDCOM$LIBRARY: -dlldata DLLDATA.C 

Change your command to the following:


  MIDL -Oicf server.idl -IDCOM$LIBRARY: -dlldata DLLDATA.CXX 

If you want to continue to use the C compiler to build your generated files, simply specify them as .C files on your command line.

Note

If you previously accepted the default file names, and want to continue to use the C compiler to build the IDL files, you must specify every IDL file on the command line.

For example, if your MIDL command was similar to the following:


  MIDL -Oicf server.idl -IDCOM$LIBRARY: -dlldata DLLDATA.C 

Change it to the following:


  MIDL -Oicf server.idl -IDCOM$LIBRARY: -dlldata DLLDATA.C -guids 
       GUIDS.C -proxy SERVER_P.C 

7.2.4 Required MIDL Switches

When running MIDL on OpenVMS, you must specify the -Oicf MIDL command-line switch.

7.2.5 Required Include Directories

MIDL components typically import UNKNWN.IDL , which contains the component definitions for IUnknown and IClassFactory . UNKNWN.IDL and other COM-related IDL and header files are located in DCOM$LIBRARY . To build your component's IDL file, use the following switch:


-IDCOM$LIBRARY: 

7.2.6 Required Header File

The VMS_DCOM.H header file contains macro definitions that enable your COM for OpenVMS application to compile properly with Bristol's Wind/U Win32 environment. You must include this header file in every source file and header file you create that relies on COM APIs or Win32 APIs. Because the files generated by MIDL rely on parts of the Win32 environment, Compaq has modified the MIDL compiler for OpenVMS to include VMS_DCOM.H in all output files.

7.3 Step 3: Compile the COM Application

The following sections describe how to compile COM for OpenVMS applications.

Note

COM application developers need access to the OpenVMS Registry to register and control access to a given application. For more information about OpenVMS Registry privileges, see Section 12.5.1 and Section 6.3.

7.3.1 Required Macro Definitions

The VMS_DCOM.H file defines several macros used by the Wind/U Win32 environment. An include statement that specifies this header file should be the first noncommented line in any source file (code or header files) that you write. However, this is not always guaranteed to be true for files generated by MIDL. Be sure to always include the following /DEFINE qualifier in all of your CXX commands:


 /DEFINE=(UNICODE=1,_WINDU_SOURCE=0X041000,_WIN32_DCOM) 

The UNICODE macro ensures that the wide character variants of Win32 APIs and data structures are enabled when you compile your code. (This macro is also defined in VMS_DCOM.H .) Omitting this macro can lead to compilation failures when building with the Wind/U Win32 environment.

The other two macro definitions are recognized by the Wind/U header files and are required to ensure the proper definition of structures and COM APIs.

7.3.2 Required Include Directories

COM for OpenVMS applications typically require header files that come from DCOM$LIBRARY .

Include the following qualifier in your C and CXX commands:


 /INCLUDE=DCOM$LIBRARY 

If you already have an /INCLUDE qualifier in your command line, modify the command to include DCOM$LIBRARY .

7.3.3 Required Header File: VMS_DCOM.H

The VMS_DCOM.H header file defines several macros used by the Wind/U header files.

Include this header file as the first noncommented line in your source files (both header files and implementation files).

7.3.4 Required C++ Qualifiers

You must specify the following C++ qualifiers when you build COM for OpenVMS applications:

7.4 Step 4: Link the COM Application

To build a COM for OpenVMS application, you must build both client and component images. Because you can implement a component as either an in-process component or an out-of-process component, you must build either a shareable image or an executable image, or both. If you are creating a new interface, you must also build a proxy/stub shareable image, unless you are using the IDispatch interface. In that case, the Automation Marshaler will be used instead of the proxy/stub shareable image. The proxy/stub shareable image provides an interface-specific object that packages parameters for that interface in preparation for a remote method call. A proxy runs in the sender's address space and communicates with a corresponding stub in the receiver's address space.

The following sections describe the steps you must follow to link the client, component, and proxy/stub images.

7.4.1 Linking the Client and the Out-of-Process Component

Although you do not need to specify any qualifiers to link the client or the component executable images, you must link both images with the following:

The specific link-time dependencies are as follows:

If you have one or more C++ modules, use the C++ linker (CXXLINK) instead of the standard OpenVMS linker so you can specify the location of your C++ repository (/CXX_REPOSITORY qualifier). For example:


$  CXXLINK/your-specific-linker-qualifiers list-of-object-modules, -
_$ DCOM$WIN32:WINDU.OPT/OPTIONS, DCOM$LIBRARY:DCOM.OPT/OPTIONS -
_$ application.OPT/OPTIONS /REPOSITORY=[.CXX_REPOSITORY]

Other ways of including the options file are as follows:

7.4.2 Linking the In-Process Component Shareable Image

The component in-process shareable image dependency list differs slightly from that of the client and component executables. The specific link-time dependencies are as follows:

7.4.2.1 Creating a Symbol Vector

Linking the in-process component shareable image requires that you create a symbol vector for the entry points that COM for OpenVMS expects to call within the shareable image. The Win32 run-time environment enforces a naming standard on the DllMain entry point, which must contain the following:

For example, a component shareable image with the name CMPNT$SHR would define the symbol vector using the following options file:


! 
! The list of symbols exported by CMPNT$SHR.EXE. 
! 
SYMBOL_VECTOR=(- 
        _WindU_DllMain_CMPNT$/DllMain  = PROCEDURE,- 
        DllGetClassObject               = PROCEDURE,- 
        DllCanUnloadNow                 = PROCEDURE,- 
        DllRegisterServer               = PROCEDURE,- 
        DllUnregisterServer             = PROCEDURE) 

A component shareable image with the name CMPNT_SHARE would define the symbol vector using the following options file:


! 
! The list of symbols exported by CMPNT_SHARE.EXE. 
! 
SYMBOL_VECTOR=(- 
        _WindU_DllMain_CMPNT_SHARE/DllMain  = PROCEDURE,- 
        DllGetClassObject               = PROCEDURE,- 
        DllCanUnloadNow                 = PROCEDURE,- 
        DllRegisterServer               = PROCEDURE,- 
        DllUnregisterServer             = PROCEDURE) 

7.4.3 Linking the Proxy/Stub Shareable Image

The proxy/stub shareable image dependency list differs slightly from that of the client and component executables. The specific link-time dependencies are as follows:

7.4.3.1 Creating a Symbol Vector

Linking the proxy/stub shareable image is more involved because you must create a symbol vector for the entry points that COM for OpenVMS expects to call within the shareable image. The Win32 run-time environment enforces a naming standard on the DllMain entry point, which must contain the following:

For example, a proxy/stub shareable image with the name PROXY$SHR would define the symbol vector using the following options file:


! 
! RPC Shareable Image 
! 
 SYS$LIBRARY:DCOM$RPCRT4_SHR.EXE/SHARE 
! 
! 
! The list of symbols exported by PROXY$SHR.EXE. 
! 
SYMBOL_VECTOR=(- 
        _Windu_DllMain_PROXY$/DllMain   = PROCEDURE,- 
        DllGetClassObject               = PROCEDURE,- 
        DllCanUnloadNow                 = PROCEDURE,- 
        GetProxyDllInfo                 = PROCEDURE,- 
        DllRegisterServer               = PROCEDURE,- 
        DllUnregisterServer             = PROCEDURE) 

A proxy/stub shareable image with the name PROXY_SHARE would define the symbol vector using the following options file:


! 
! RPC Shareable Image 
! 
 SYS$LIBRARY:DCOM$RPCRT4_SHR.EXE/SHARE 
! 
! 
! The list of symbols exported by PROXY_SHARE.EXE. 
! 
SYMBOL_VECTOR=(- 
        _Windu_DllMain_PROXY_SHARE/DllMain = PROCEDURE,- 
        DllGetClassObject                  = PROCEDURE,- 
        DllCanUnloadNow                    = PROCEDURE,- 
        GetProxyDllInfo                    = PROCEDURE,- 
        DllRegisterServer                  = PROCEDURE,- 
        DllUnregisterServer                = PROCEDURE) 


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
6539PRO_007.HTML