4 — Miscellaneous Notes


[Previous] [Next] [Contents] [Index]


This chapter contains miscellaneous information useful when developing DCE applications with PC-DCE. It contains the following sections:

4.1 Developing C++ Applications
4.2 DCE Message Catalogs
4.3 Static Initialization of Constants
4.4 Microsoft RPC Interoperability
4.5 Name Service Interface Gateway
4.6 DCECP Functionality
4.7 .DBG Files
4.8 Max Call Requests
4.9 External Time Providers
4.10 Controlling RPC Timeouts
4.11 Setting a Session-Wide Login Context
4.12 Converting an Exception to an Error Status Code
4.13 Starting PC-DCE Services from the Command Line
4.14 Developing Thread-Safe Code
4.15 Setting Thread Priority Under Windows
4.16 Using Per-Thread Login Contexts
4.17 Using DCE Pipes
4.18 Runtime Version Requirement

4.1 Developing C++ Applications

In order to use the XIDL/DCE IDL compiler for C++ development, you need to have a C++ environment available on a machine where the PC-DCE ADK is installed. Currently, Microsoft Visual C++ Version 4.1 or later is the only supported environment. For portability reasons, stubs generated in this environment and the runtime library (libidlcxx.lib) used in this environment do not use features such as templates, exceptions, and multiple inheritance.

4.1.1 Typical Development Procedure

The following steps represent a typical development flow while using XIDL/DCE IDL C++ support:

  1. Create an interface definition using IDL.

  2. Identify operations that create remote objects in the IDL file with the cxx_new attribute in the attribute configuration (.acf) file.

  3. Invoke the IDL compiler with the -lang cxx option to generate the C++ header and the client/server stubs.

  4. For the client, develop the code that uses the class generated. The client can use the static member function <class>::bind() to bind to any named or exported remote object. The client can also optionally set rebinding policy on communication failures with remote objects using the <class>::SetRebind() static member.

  5. For the server, develop the implementation of the class and initialization code that performs the RPC setup and desired object registration (using the <class>::register_named_object() static member function).

  6. Link application C++ code and the stubs into an executable file.

XIDL/DCE IDL also supports passing of C++ objects as RPC parameters. Applications may use the represent_as parameter attribute to pass in the object or the cxx_delegate attribute on the interface definition to pass the object by reference.

By default, XIDL/DCE IDL with the -lang cxx option generates a manager class from which the manager implementation may be derived. This can be prevented with the -no_cxxmgr option for a manager implementation in the C language.

4.1.2 Pthread Exceptions vs. MS Visual C++

When the pthread header files are included by C++ code, the exception handling macros (CATCH, TRY, ENDTRY, etc.) are renamed with the prefix DCE_ (DCE_CATCH, DCE_TRY, DCE_ENDTRY, etc.) by default. If your C++ code expects to use the original macro names, you must define the STANDARD_DCE_EXCEPTIONS macro either by using the CL command line option -DSTANDARD_DCE_EXCEPTIONS or by adding the #define STANDARD_DCE_EXCEPTIONS statement to the C++ source code prior to including <pthread.h> or <dce/exc_handling.h>.

Be aware, however, that the DCE and C++ exception handlers are not compatible.

The DCE default names are always used when compiling a C application.

4.1.3 Calling Conventions vs. MS Visual C++

Since there are a number of different function-calling conventions (call sequences) available in C and C++, there are some issues when interfacing between user-written code and IDL-generated code. In particular, functions that are called through the server manager interface are declared with the IDL_MGR_CALL_SEQ macro which is defined as __cdecl by default. This is the compiler's default for functions written in C.

This macro may be redefined on the CL command line in situations where __cdecl is inappropriate or unusable. For example, to specify the standard call convention, you can add the compiler option -DIDL_MGR_CALL_SEQ=__stdcall. To use the default C++ calling convention (also known as "thiscall"), define the macro as -DIDL_MGR_CALL_SEQ="" (i.e., nothing). Such a routine will not be callable from outside C++.

When generating new code, Entegrity recommends that you use the IDL_MGR_CALL_SEQ macro wherever classes are derived from IDL-generated manager classes.

4.2 DCE Message Catalogs

DCE message catalogs are located in:

install_directory\opt\dcelocal\nls\msg\en_US.ISO8859-1

4.2.1 Generating Message Catalogs from .sams Files

Message catalogs (.cat) generated for application-defined .sams (symbol and message strings) files should be compatible with PC-DCE. Currently, the PC-DCE sams utility does not support the -c command line option, which generates the message catalogs.

In order to generate the necessary message catalogs:

  1. Use MSVC 2.2 or later.

  2. Generate the message file (.msg) from the .sams file using sams with the -m command line option:

    sams -m app.sams
    

  3. Use the PC-DCE strtbl.exe to generate a resource (.rc) file with definitions for the message strings:

    strtbl app_svc.rc dceapp.msg
    

  4. Compile the generated resource file using the resource compiler.

  5. Build a DLL that includes the compiled resources with a dummy entry point and name it dceapp.cat.

4.2.2 NT_EVENTLOG Routing

On Windows NT systems, applications may direct serviceability messages to the NT event log by specifying the NT_EVENTLOG route. Select this route by placing the keyword NT_EVENTLOG in the routing specification. For example:

FATAL:NT_EVENTLOG

This example directs all fatal DCE serviceability messages to the NT event log.

See The Open Group DCE 1.1 Application Development Guide for more information on routing and DCE serviceability.

4.3 Static Initialization of Constants

The PC-DCE runtime DLL exports several DCE constants which cannot be included in static initialization. For example, if an application wants to import the rpc_x_comm_failure exception into an array, the following is invalid:

static EXCEPTION *pExcList[]={&rpc_x_comm_failure,...};

The same can be initialized as:

pExcList[0]=&rpc_x_com_failure ;

4.4 Microsoft RPC Interoperability

Since Microsoft uses a "DCE-compliant" Remote Procedure Call (RPC) layer, PC-DCE can use Microsoft RPC DCE clients and servers as long as no security or CDS namespace operations are also being used. However, stub files are not compatible. You must use the MIDL compiler to generate a Microsoft RPC program and the PC-DCE IDL compiler to generate a DCE RPC program.

If you want Microsoft RPC Clients to read entries from the CDS namespace, set up an NSID in your cell. This does not let Microsoft RPC servers write to the CDS namespace.

4.5 Name Service Interface Gateway

The Name Service Interface Gateway (nsid), allows remote systems that only have RPC services to use the DCE CDS name service. The nsid runs on one or more DCE systems in the cell and acts on behalf of the remote system to execute the RPC name service API calls. Through a hidden level of indirection, the nsid allows the PC to appear as if it is directly involved in the broader cell namespace.

4.5.1 Supported nsid Protocols

The nsid is currently designed to listen on TCP/IP and DECnet. It checks to ensure that each protocol sequence is supported before using it. If neither TCP/IP or DECnet are supported, then the nsid will exit with an error message to that effect.

4.5.2 How the nsid Works

An application on a PC running Microsoft Windows makes a call to familiar name-service procedures, such as rpc_ns_binding_export (or, in the Microsoft native format, RpcNsBindingExport). Within these procedures, the parameters are passed using RPC to the nsid.

The nsid:

  1. Receives the parameters from the PC

  2. Converts them to native DCE format

  3. Makes a call to the native rpc_ns_binding_export procedure that corresponds to the procedure called on the PC

The CDS server:

  1. Receives the parameters

  2. Performs the requested operation

  3. Returns the results to the nsid

The nsid:

  1. Converts the results back into a format the PC caller can understand

  2. Returns them to the PC using RPC

The PC client now has the results of the call and can take appropriate action.

The system where the nsid is running can be a different system from where the CDS server is running, because any operation defined by the NSI can be called from any member of the cell.

4.5.3 How the PC Client Finds the nsid

The PC client queries information contained in a database called the registry. On Windows 98, the registry is in a file in the PC root directory, called RPCREG.DAT. In RPCREG.DAT, the first four parameters completely define how the nsid is to be contacted, and consist of:

For example, within the procedure RpcNsBindingLookupBegin RPCREG.DAT is read and a remote procedure call is made to the binding represented by that set of parameters.

On Windows NT and Windows 2000, the Registry is an integral part of the operating system's services.

For details on how to set up the registry for Windows NT and Windows 2000, see Chapter 5 of the PC-DCE Adminstrator's Guide

4.5.4 APIs Supported by the nsid

All of the NSI is supported by the nsid, but not on all platforms. For instance, because Windows provides only client RPC services, server-only APIs are not supported.

The following list of APIs is in the DCE style. The native Microsoft style is slightly different. For example, rpc_ns_group_delete appears as RpcNsGroupDelete in the Microsoft native style. A dceport.h INCLUDE file is provided to enhance application portability on Microsoft platforms.

rpc_ns_binding_import_begin
rpc_ns_binding_import_next
rpc_ns_binding_import_done
rpc_ns_binding_lookup_begin
rpc_ns_binding_lookup_next
rpc_ns_binding_lookup_done
rpc_ns_binding_export
rpc_ns_binding_unexport
rpc_ns_group_mbr_add
rpc_ns_group_mbr_remove
rpc_ns_group_delete
rpc_ns_mgmt_inq_exp_age
rpc_ns_mgmt_set_exp_age
rpc_ns_profile_elt_add
rpc_ns_profile_elt_remove
rpc_ns_profile_delete
rpc_ns_mgmt_entry_create
rpc_ns_mgmt_entry_delete
rpc_ns_mgmt_entry_inq_if_ids
rpc_ns_mgmt_binding_unexport
rpc_ns_entry_expand_name
rpc_ns_group_mbr_inq_begin
rpc_ns_group_mbr_inq_next
rpc_ns_group_mbr_inq_done
rpc_ns_profile_elt_inq_begin
rpc_ns_profile_elt_inq_next
rpc_ns_profile_elt_inq_done
rpc_ns_entry_object_inq_begin
rpc_ns_entry_object_inq_next
rpc_ns_entry_object_inq_done

4.6 DCECP Functionality

The DCE Control program (which is a tcl interpreter extended with DCE-specific commands) may be embedded in applications that are themselves tcl interpreters. When embedding dcecp functionality into an application, you must include the tcl.h and dcecp.h header files. These files are shipped as part of the ADK.

In addition, dcecp and tcl are shipped as DLLs rather than static libraries in order to save paging space. dcecp.exe is a thin veneer above dcecp.tcl (lib), which simply initializes the interpreter and starts the tcl command loop.

4.7 .DBG Files

Symbol files corresponding to all DCE executables (including those in both the runtime and server kits) are installed under the install_directory/bin/symbols directory. In order to debug PC-DCE (optimized) executables, these symbol files need to be copied into the default symbol directory (for example, windows_directory/symbols) thus preserving the directory structure. This step is not necessary if windbg is being used for debugging and the -y command line option is used to specify the symbol path; msdev has no such option and requires the .dbg files in the default location.

After the debug files are installed, you can set breakpoints inside any function within PC-DCE executables and DLLs by editing the breakpoints and specifying the name of the function to break in. For functions that use the __stdcall convention (as most of the functions exported from dce32.dll do), function calls need to be suffixed by @size of arguments. For example, if you are setting a breakpoint in the function dce_msg_define_msg_table which takes a pointer, unsigned32 and a pointer as arguments, you should specify the function to break in as _dce_msg_define_msg_table@12.

Once the debugger stops at the breakpoint of interest, you can now examine registers, call stacks and variables.

4.8 Max Call Requests

OSF DCE v1.2.2 had a limitation where if you specified a max call request argument with certain RPC functions, the argument was ignored and the default max call request located in the header file was used instead. This limitation affected the following functions:

PC-DCE lets you specify a max call request with these functions that is greater than the default, enabling more endpoints upon which the server can listen for client requests.This can help reduce the possibility of a server rejecting a client call due to the socket queue becoming full.

4.9 External Time Providers

Entegrity does not provide a DTS provider implementation. However, Entegrity does support the DTS provider interface so that you can add your own time provider into DTS. The dtsprovider.idl file is shipped with the PC-DCE Application Developer's Kit (ADK). For information on implementing time providers, refer to the OSF DCE Application Development Guide.

4.10 Controlling RPC Timeouts

In certain situations, you may want to exercise more control over the timeout value of RPCs that regularly fail or generally do a better job of handling unexpected RPC failures. The timeout value for connection-oriented services (such as TCP) cannot be controlled at the API level because that attribute value is determined by the underlying transport layer. However, the datagram service (UDP) works differently. Default timeouts are 2 minutes for TCP and 45 seconds for UDP.

You can use the DCE API rpc_mgmt_set_com_timeout() to define the timeout for the datagram protocol. While TCP is often the protocol of choice (because it offers guaranteed delivery), some of your specific RPCs or your test environment might want to use UDP to take advantage of the control it offers in this area. With PC-DCE for Windows 3.1 and PC-DCE, you can tune the timeout from a few seconds to 30 seconds, to several minutes and longer.

After your client application gets a binding, make your call. For example:

rpc_mgmt_set_com_timeout(binding_h, 0, &status);

where a value of 0 represents the minimum timeout and a value of 10 attempts to communicate forever. Although the values in between do not represent actual seconds, they are instead arbitrarily assigned and presented in ascending order; each is longer than the previous value.

You can have your client code selectively secure a UDP binding or use the RPC_SUPPORTED_PROTSEQS environment variable to restrict the runtime to one protocol or the other, for example: RPC_SUPPORT_PROTSEQS=ncadg_ip_udp.

4.11 Setting a Session-Wide Login Context

If your application uses the standard DCE sec_login functions, it will create a login context that applies only to that specific instance of the application. If you run such an application, open a command prompt window and issue the klist command, it will not list the application's login context.

The PC-DCE dce_login program sets a session-wide login context. If you open a command prompt, run dce_login, close the command prompt, and then open a second command prompt and run klist, it will list the credentials created by dce_login. You can create such a session-wide login context for your application by using the following functions:

For more information on these functions, refer to Chapter 5 on page 31.

4.12 Converting an Exception to an Error Status Code

Some programs may cause an unhandled exception to be raised by the DCE runtime. Symptoms include:

You can trap the exception that is being raised and convert it to an error message. At that point you can change the application or at least handle similar failures better. Here's an example of how to CATCH an exception for the RPC made in the Greet sample.

TRY
{
    for (i = 0; i < reps; i++)
    {
        greet (binding_h, greeting, reply);
        printf ("The server says: %s\n", (LPSTR) reply);
        pthread_yield ();
    }
}

CATCH_ALL
{
exc_get_status (THIS_CATCH, &status);
ERROR_CHECK (status, "This was caught during the RPC");
}

4.13 Starting PC-DCE Services from the Command Line

PC-DCE integrates all DCE services directly into the Windows 2000 and Windows NT services layer. Typically, you manage DCE services from the PC-DCE Service Panel. For debugging purposes only, you can start the DCE services manually from the command line. Use the commands in the following list to start DCE manually. This list is complete and is presented in the order that the services would start if activated automatically.

For the lightweight client, there are no daemons to start with the possible exception of rpcd if the client is so configured.

For a full client:

prompt> 	rpcd -d -f
prompt> 	sec_clientd -d -v
prompt> 	cdsadv -v 
For a server:

prompt> 	rpcd -d -f
prompt> 	sec_clientd -d -v
prompt> 	secd -v
prompt> 	cdsd -v
prompt> 	cdsadv -v

4.14 Developing Thread-Safe Code

Symptoms that you may see if your server manager code is not thread-safe include:

Sometimes the RPC server manager code includes operations such as file I/O and database update routines that are not thread-safe. To use DCE pthread mutex lock to make sure the routines are not executed by more than one server thread:

4.15 Setting Thread Priority Under Windows

Currently, pthread_attr_setpri() takes priority values from 1-15 where levels 1-9 map to Above Normal priority and levels 10-15 map to Highest priority. Note that the Windows 2000 and Windows NT environment makes no distinction between values within each range. For example, a one has the same priority as nine (Above Normal). At this time, Entegrity does not allow any priority to go below normal.

To set the base priority of a thread below normal, you can call the Win32 API SetThreadPriority function. The following priority levels are available using this function: Lowest, Below Normal, Normal, Above Normal, Highest.

4.16 Using Per-Thread Login Contexts

Standard DCE allows you to have as many login contexts as you wish — you supply the login context handle when annotating an RPC binding handle with security or when negotiating a GSS-API session. However, standard DCE lets you set only one process-wide default login context (using the sec_login_set_context() call).

PC-DCE enhances standard DCE to allow default login contexts on a per-thread basis. Your application calls sec_login_set_thread_context() to set up the per-thread context. Then, calling sec_login_get_current_context() from that thread returns the per-thread context rather than the per-process context. To break the association between a thread and a login context you call sec_login_unset_thread_context().

One example of the usefulness of per-thread login contexts is when you can not pass around a DCE login context handle within your application. This happens many times when you are calling across a standardized interface, such as ODBC. ODBC has no place in the interface to pass down a DCE login context handle to an underlying DCE-enabled ODBC driver, so these drivers simply call sec_login_get_current_context() to get the per-process login context. This works fine in a 2-tier environment, but breaks down in a 3-tier delegated environment.

In the 3-tier environment, the intermediate server has one login context for each client that is accessing it, reflecting the fact that the server is acting on behalf of the client. Without per-thread login contexts, you would need to mutex-protect the per-process login context and single-thread each user through the ODBC layer. With per-thread login contexts, you associate the delegated login context with the thread, make your ODBC calls, and then break the association.

For details on the Entegrity extensions, refer to Chapter 5 on page 31.

4.17 Using DCE Pipes

Consider using DCE pipes in situations where:

The Guide to Writing DCE Applications by Shirley, Wu, and Magid (O'Reilly & Associates) discusses this topic in detail. Entegrity has ported the Transfer_data sample to PC-DCE. You can download this sample from the following location: ftp://ftp.entegrity.com/pub/dce/pcdce/samples/xferdata.zip.

4.18 Runtime Version Requirement

If you build applications using the current PC-DCE Application Developer's Kit, you must run them with the PC-DCE runtime at the current revision or later.


[Previous] [Next] [Contents] [Index]


To make comments or ask for help, contact support@entegrity.com.

Copyright © 1997-2003 Entegrity Solutions Corporation & its subsidiaries