The undersigned, appointed by the Dean of the Graduate School, have examined the thesis entitled

 

Interconnecting Personal Computers with the Distributed Computing Environment

 

presented by

James E. Ries

 

a candidate for the degree of

Master of Science

 

and hereby certify that in their opinion it is worthy of acceptance.

 

 

______________________________

Dr. Gordon K. Springer

 

 

______________________________

Dr. Anupam Joshi

 

 

______________________________

Dr. Timothy B. Patrick


 

INTERCONNECTING PERSONAL COMPUTERS WITH THE DISTRIBUTED COMPUTING ENVIRONMENT

 

 


A Thesis Presented to the Faculty of the Graduate School

University of Missouri-Columbia

 

 

In Partial Fulfillment of the Requirements for the Degree

Master of Science

 

 


by

JAMES E. RIES

Prof. Gordon K. Springer, Thesis Supervisor

JULY 1998


Acknowledgements

 

This has been a long journey with many twists and turns.  I would certainly still be lost, far back on the path were it not for the patience, insistence, and good sense of Professor Gordon Springer, who helped me over the blockages in the path and demanded that I keep going.  I would truly be lost on this path and the greater path of life without the support of my wife, Laura, who gave up many plans to instead see that I had the opportunity to work on this document and all of the research which went before it.  I would also be far short of the end, without the help of my daughter, Abbie, who was kind enough to start sleeping through the night at a very young age.


Abstract

 

 

This thesis seeks to demonstrate that personal computers can be integrated into the Distributed Computing Environment (DCE) and to illustrate the compromises that exist among various methods of such integration.  An existing sample DCE application, BINOP, is ported using two of the possible methods.  The strengths and weaknesses of each method are explicated.  Several third party software packages are examined as a means for simplifying the porting of DCE applications, and as ways to enhance the function of DCE applications running on personal computers.

            In acknowledgement of the general movement toward object-oriented paradigms, various attempts to bring object-oriented technology to distributed computing are discussed with respect to the personal computer and to the synergies of these approaches with DCE.  These include Microsoft’s Distributed Component Object Model (DCOM), Hewlett Packard’s Object-Oriented DCE (OODCE), and the Object Management Group’s (OMG) Component Object Resource Broker Architecture (CORBA).


Table of Contents

 

Acknowledgements....................................................................................................... ii

Abstract............................................................................................................................ iii

Table of Contents.......................................................................................................... iv

List of Figures................................................................................................................. vi

1. Introduction................................................................................................................. 1

1.2 The challenges...................................................................................................... 1

1.3 Why DCE?............................................................................................................. 5

1.4 Programming in the DCE world.......................................................................... 7

1.5 What about the future?....................................................................................... 10

2. Choosing Platforms................................................................................................ 11

2.1 Microsoft DOS and Windows 3.x...................................................................... 11

2.2 Microsoft Windows 95........................................................................................ 17

2.3 Microsoft Windows NT....................................................................................... 18

2.4 IBM OS/2 and Apple Macintosh........................................................................ 19

2.5 OS choices conclusion....................................................................................... 20

3. What You Need......................................................................................................... 22

3.1 Supported protocol stacks................................................................................. 23

3.2 Development kits................................................................................................ 24

3.3 Hardware............................................................................................................. 25

3.4 Summary of what you need................................................................................ 25

4. Third Party Tools...................................................................................................... 27

4.1 Digital DCE for Windows NT and Windows 95............................................... 27

4.2 Gradient’s PC/DCE............................................................................................ 29

4.3 Hewlett-Packard OODCE.................................................................................. 30

5. Porting An Existing OSF DCE Application to Microsoft Platforms (BINOP) 31

5.1 Straight Microsoft................................................................................................ 32

5.2 Full DCE.............................................................................................................. 36

6. The Future (Is Sooner Than You Think)............................................................. 41

6.1 DCOM.................................................................................................................. 41

6.2 CORBA................................................................................................................ 46

6.3 WWW and DCE.................................................................................................. 48

7. Conclusion................................................................................................................ 52

Glossary.......................................................................................................................... 55

References..................................................................................................................... 57

Appendix A: BINOP Source Code........................................................................... 59


List of Figures

 

Figure 1: Microsoft Windows NT Architecture....................................................................... 9

Figure 2: Share of US PC’s Using Top Four Operating Systems........................................... 12

Figure 3: 1997 OS Shipments With PC Systems Worldwide – Market Share....................... 13

Figure 4: Summary Of Requirements For RPC On Microsoft Platforms................................ 26

Figure 5: Successful WIN32RAW Binopc Run.................................................................... 33

Figure 6: WIN32RAW Binopc Run With Communication Error........................................... 34

Figure 7: Windows NT OS Error Dialog.............................................................................. 34

Figure 8: WIN32 Binopc Run With Communication Error.................................................... 35

Figure 9: DCOM Architecture............................................................................................. 43

Figure 10: OMG’s CORBA................................................................................................ 47

Figure 11: DCE-Web.......................................................................................................... 50


1. Introduction

 

 

This thesis seeks to demonstrate that personal computers (PC’s) can be integrated into the Distributed Computing Environment (DCE) and to illustrate the compromises that exist among various methods of such integration.  The thesis was initially conceived as a tutorial on porting DCE applications to PC’s.  It was also to provide a guide to writing applications that are generally portable across all DCE and environments that support Remote Procedure Calls (RPC).  As work on the thesis progressed, it became clear that it would be necessary to not only examine ways that PC’s can be integrated into DCE, but also to explore the role of personal computers in distributed computing in general.

 

1.2 The challenges

Most computing environments deployed within businesses, schools, universities, and other organizations today are heterogeneous in nature.  That is, no one vendor’s products are used exclusively to meet all of the computing needs of all users within these organizations.  Some sub-groups may use Unix workstations from a variety of vendors, including Sun Microsystems, Digital Equipment Corporation, Hewlett Packard, and many others.  Some may use IBM standard personal computers, running such operating systems as Microsoft DOS, Microsoft Windows, Microsoft Windows 95, Microsoft Windows NT, IBM OS/2, or one of many versions of Unix.  It is also the case that these personal computers may be obtained from a wide selection of vendors.  Some users may use mainframes or minicomputers (such as IBM’s AS/400) from IBM and other sources.  In addition, many users may use some or all of these platforms at various times for differing tasks, since some platforms tend to be used for specialized purposes.

Yet, with this dizzying array of heterogeneous hardware, peripherals, and software, there exists a need for interoperability.  The information contained on one system may be needed to perform an analysis on another system.  Although data may have many representations on the disparate platforms (e.g., EBCDIC or ASCII), the information stored on each of these systems must be made to cross the boundaries among machines.  That is, the increasingly naïve users of computing systems should not have to be concerned with the technical details regarding the way data is stored or even where it is stored.  They should simply be able to find and utilize the information that they seek.

Although typical computing environments are composed of a mix of platforms, these platforms are typically interconnected through some form of network.  A larger heterogeneous network may be composed of locally homogeneous subnetworks, each operating over a possibly unique topology (e.g., ATM, ethernet, or token ring) and a possibly unique protocol (e.g., TCP/IP, IPX, Netbios, Netbeui [Netbios Extended User Interface], DECnet, etc.).  However, the subnetworks that comprise this larger network are all typically interconnected via bridges and gateways to form an intranet (which may, in fact, be connected to the global Internet).  This configuration allows an organization to exchange information among its component platforms, as long as the data can be coaxed into a format appropriate for its destination platform.  Of course, moving data from platform to platform can be a significant problem in and of itself.  It may require translation from one encoding scheme to another (such as big-endian notation to little-endian notation) and perhaps from one application’s proprietary format to another (such as Wordperfect to Word).

Moreover, performance problems can arise if large quantities of data are to be transported across the network to be operated upon by a remote computer.  This can be a very time-consuming process and can quickly use up all available bandwidth (the capacity of a network to transport data) if it is a common occurrence.  This may result in performance issues for all users of the network, not merely for the user or set of users who require the transport of the data in question.

The task for programmers to make all disparate platforms and networks work seamlessly together is immense.  What is really needed is a way for programmers to write programs in the way they are accustomed (i.e., with the assumption that data and code dwell on the same physical machine), while remapping the programmer’s code to work across the network.

Users also benefit from the concept of transparency.  A typical user of a computer system simply wishes to get work done.  That is, the user wants to know about some information and perhaps put it together with other information that exists elsewhere on the network.  It should not be up to the user to discover which physical machine or computing platform happens to house this information.  Rather, the user should employ the same means when working with data that is stored on the network or on the local workstation.

The problems presented by heterogeneity of hardware platforms and operating systems, limited communications bandwidth, and the need to transparently code distributed systems are far from trivial.  In the past (and even today), distributed applications have been built without regard to previously developed applications.  These applications are usually written utilizing the TCP/IP protocol (e.g., web browsers), the IPX protocol (e.g., Novell Netware file servers), or some other custom protocol.  This has resulted in systems that are limited with regard to platform and/or operating system, and which required highly specific expertise on the part of applications developers.  For example, many Novell Netware applications have not survived the recent and swift conversion to TCP/IP.  These problems beg for an abstraction layer which hides the specifics of individual protocols from the application developer and which allows the developer to write code with little regard for whether code executes on the local machine or on another machine located across the network.

            The client/server style of coding helps the developer to make this abstraction.  The developer creates a client application that provides, minimally, a user interface.  The client application relies upon a server that may be located remotely to do some or all of the actual computing work.  This distribution of computing effort allows the server to run in closer proximity to the data on which it operates, perhaps on the same physical machine.  This can reduce the bandwidth problems discussed earlier.  However, without some additional layer of abstraction, the distribution still does not free the developer from many of the details of wire protocols and platform dependencies.

 

1.3 Why DCE?

The Open Software Foundation (OSF; now called the Open Group [22]) has developed a standard for distributed computing called the Distributed Computing Environment (DCE).  DCE is rapidly becoming the standard for the interoperation of heterogeneous computers that run some implementation of the Unix operating system.  In fact, DCE run-time services are being incorporated into the base operating systems support provided by many manufacturers.  DCE allows clients on one platform to access servers on another, without regard to the hardware, operating system, or available network transports between and among the cooperating machines.  In theory, this frees the application developer from mundane tasks and provides a layer of abstraction on which to rest the development process: The application developer creates a client and a server, each of which should be able to run on any platform, operating system, or transport.

In practice, this works quite well for many of the operating systems that support DCE.  These include Digital Equipment Corporation’s line of Alpha workstations running Digital Unix, HP systems running HP/UX, IBM’s RS/6000 line running AIX, Silicon Graphics machines running IRIX, Cray Supercomputers, and even Sun workstations with the addition of some third party software.  In many environments, these platforms can co-exist using DCE very effectively.  However, many real environments today, both academic and commercial, contain large numbers of personal computers based on the IBM standard using Intel processor chips.  The vast majority of these machines run Microsoft Corporation operating systems; primarily Microsoft DOS, Microsoft Windows 3.0 and successors (a.k.a. Windows 3.x), Microsoft Windows 95 and its successors (a.k.a. Windows 9x), and Microsoft Windows NT.  In order to make a DCE application available to the greatest number of users, the client portion (at least) must be made to run on the various Microsoft-based operating systems.

Microsoft itself has recognized the need for its operating systems to function in the DCE world.  To facilitate this, Microsoft provides support for the core component of DCE; the remote procedure call (RPC; see [19]).  The RPC is a standard way to create a procedure which runs on a server that can be called from a client just as though this procedure were a normal procedure, local to the client.  In the case of DOS and Windows 3.x, this support is in the form of a toolkit of redistributable dynamic link libraries (DLL’s) that can be freely added to machines running one of these operating systems.  In the case of Windows 9x and Windows NT, support is built into the system itself.

However, Microsoft’s implementations of RPC’s are not based on the Open Group’s source code for DCE, as are most other manufacturers’ implementations.  Worse, Microsoft does not provide interoperability with other DCE functions that are standard in true DCE environments.  Such important functions as Cell Directory Service (CDS), security service, Distributed Time System (DTS), and DCE threads are unavailable in current Microsoft operating systems.  CDS provides a mechanism for discovering services which are available within a DCE cell.  DTS is a service which keeps time accurate and consistent among the cell members.  The security service provides authentication and encryption capability, and DCE threads are the standard POSIX threads which allow multiple threads of execution within a single program.

Due to the limited compatibility, many programs originally written for the DCE environment cannot be run, or even compiled, on Microsoft platforms.  The goal of this paper is to explore ways that the popular PC environments can function as a part of the Distributed Computing Environment.  In some cases this entails adding additional software to these platforms, writing work-around code to deal with incompatibilities, and sometimes even submitting to a loss of functionality.  Each of the popular PC environments has its own challenges and limitations.

 

1.4 Programming in the DCE world

The Distributed Computing Environment runs best and is fully functional on a variety of Unix based platforms and the IBM mainframe systems (e.g., AS/400, VM, and OS/390).  By fully functional, it is meant that all of the standard DCE services are available on these platforms.  The basic services (see [14]) include the Cell Directory Service (CDS), the Distributed Time Service (DTS), security services, Remote Procedure Calls (RPC), and the Distributed File System (DFS).  A fully featured DCE client machine has a CDS clerk (a clerk is a process running on a client machine which provides access to a given service), a DTS clerk, a Security clerk, DFS client software, and a DCE runtime library.  Each DCE server system may have some or all of the client software, plus it may include a CDS server, a DTS server, a DFS server, and a Security server.

A typical developer of a DCE application can assume that most or all of these services are available to his or her program.  Furthermore, since DCE has grown out of Unix and Unix-like environments, the developer typically assumes that standard Unix operating systems calls and standard ANSI C library support is available.  In general, it is assumed that the target system is POSIX compliant.

POSIX is an attempt to standardize the disparate flavors of Unix.  It is a set of IEEE standards (IEEE 10003.0 to 10003.22 a.k.a. POSIX level 0 to POSIX level 22) which define minimal requirements for an operating system to be considered compliant.  There are several levels of POSIX compatibility.  One of the serious problems for writing applications which function across Unix and PC platforms is that most PC platforms are not strictly POSIX compliant.  Even Microsoft Windows NT (NT) is merely POSIX level 1 compliant.  Since threading, for example, is not a requirement until POSIX level 4a, applications running on NT cannot presume thread support.

An even more difficult problem is NT’s support for POSIX.  POSIX on NT is implemented as a compatibility “subsystem”.  Windows NT was designed with a protected kernel that provides basic operating system services.  On top of this kernel, a layer of subsystems is provided which run as standard user mode applications (see Figure 1).  These subsystems add richer functionality that is not available directly from the kernel.  Supplied with the OS, are OS/2 and POSIX subsystems.  These subsystems are on an equal footing with standard Win32 applications in terms of services available to them.  However, these subsystems have their own executable formats.  They cannot be linked with standard libraries available to typical Win32 applications.


Figure 1: Microsoft Windows NT Architecture

 From “The Foundations of Microsoft Windows NT System Architecture” whitepaper by Microsoft Corporation, September 1997.

 

Since POSIX applications cannot link to standard Win32 libraries, they cannot take advantage of the rich functionality available to typical Win32 applications. Since there are few libraries available for the POSIX subsystem, POSIX applications are reduced to the role of poor step-relatives when compared to their Win32 counterparts.  Further confounding the situation, is the fact that DOS, Windows 3.x, and Windows 95 do not even purport to be POSIX compliant, as does NT.

 

1.5 What about the future?

It seems clear that DCE will continue to be important for the foreseeable future.  While arguments about what to distribute (e.g., the current concern with distributed object technology) may continue, there seems to be little question on the choice of whether or not to distribute.  The major camps regarding distributed objects both support DCE after a fashion.  The Object Management Group’s (OMG) Common Object Request Broker Architecture (CORBA) (see http://www.omg.org/corba/corbiiop.htm) standard contains provisions for interoperation with DCE.  Microsoft’s Distributed Component Object Model (DCOM) sits securely atop DCE’s RPC.  The Open Group has recently published standards for interoperation of the World Wide Web (WWW) with DCE (see http://www.camb.opengroup.org/RI/www/dceweb/).  Each of these is further examined in Section 6.

DCE has been making great strides into corporate America and the world as well.  As downsizing and right-sizing continue to drive companies away from completely centralized databases and applications, client-server and peer computing have made DCE an attractive standard.  As DCE continues to penetrate corporate America, it will become increasingly important for personal computers (deployed on great numbers of corporate desktops) to be able to participate as standard DCE platforms.  This project demonstrates that it is possible for personal computers to fulfill this role, with varying success, depending on the operating system and third party tools available.


2. Choosing Platforms

 

Software developers who wish to deploy distributed applications must make allowances for the operating systems and platforms that are deployed within their target organizations.  Although the developer may wish to leverage DCE, the target platforms may not support DCE, or may support it only partially.  Nonetheless, few organizations can afford to replace large numbers of systems, and this may require that developers find ways to integrate existing platforms into their solutions.

 

2.1 Microsoft DOS and Windows 3.x

The Microsoft Disk Operating System (DOS) and the windowing system that runs on top of it, Microsoft Windows 3.x, are very nearly ubiquitous in the PC environment.  Almost every PC ever made has been bundled with some flavor of DOS (including some compatible non-Microsoft versions such as products from IBM and Digital Research).  Since the introduction of Microsoft Windows 3.0, almost all PC’s are also bundled with Windows.  Windows 9x and Windows NT have replaced DOS and Windows 3.x (see Figure 3) in recent years in bundles with new machines.  However, the two-headed operating system of DOS/Windows 3.x remains deployed on vast numbers of corporate, academic, and home personal computers (see Figure 2).

 


Figure 2: Share of US PC’s Using Top Four Operating Systems

From Computer Intelligence InfoBeads study.  Used in accordance with “InfoBead End-User License Agreement” (see http://www.ci.infobeads.com/InfoBeads/Pages/Viewer/VIEWER_REGISTRATION.ASP?INFOBEAD_ID=C0000938AA)

 

 

 


Figure 3: 1997 OS Shipments With PC Systems Worldwide – Market Share

From Computer Intelligence InfoBeads study.  Used in accordance with “InfoBead End-User License Agreement” (see

http://www.ci.infobeads.com/InfoBeads/Pages/Viewer/VIEWER_REGISTRATION.ASP?INFOBEAD_ID=M0000913AB)

 

These facts might lead one to the conclusion that any project seeking to integrate personal computers into the world of the DCE would need to include support for DOS and Windows 3.x.  Unfortunately, these operating systems were not designed with remote computing in mind, and therefore do not support many of the features that make it possible to fully integrate them with DCE.

There are, however, “work arounds” that allow some degree of interoperability for these operating systems.  Microsoft provides a freely distributable product called Microsoft Remote Procedure Call Run-time that adds basic RPC functionality to DOS and Windows 3.x, but lacks all of the other standard DCE services.  By installing the Microsoft Remote Procedure Call Run-time on a DOS or Windows 3.x workstation, some very simple DCE applications can be made to run in this environment.  However, as shall be discussed later, such an application not only suffers from the lack of the aforementioned DCE services, but may also require a significant porting effort to compensate for differences in system calls, and general lack of POSIX compliance displayed by this environment.

 

2.1.2 Third party solutions

Another possible way to bring DOS/Windows 3.x into the DCE fold is through a set of commercial products from Gradient Technologies, Inc. (see http://www.gradient.com/Products/Pc-dce/dce_frt.htm) collectively called PC-DCE.  PC-DCE consists of the PC-DCE Runtime Kit which must be installed on each workstation that runs a DCE application that has been ported using PC-DCE plus an Application Developer’s Kit which provides all of the tools (e.g., IDL compiler, UUID Generator, libraries, and source headers) needed by a developer to port or write a DCE application.  Additional information on the Gradient product is provided in Section 4.2.  Even presuming that the PC-DCE product solves all other incompatibility issues between DOS/Windows 3.x and DCE proper, it is still a significant disadvantage to a developer to require a “for-cost” runtime that all users of a product would have to purchase or that would have to be redistributed with the product, thus increasing the base product cost.

However, even with third party additions to DOS and/or Windows 3.x, there is no support for the server portion of DCE services.  That is, the client (or “clerk” in DCE terminology) side of the various services may be available if the appropriate third party add-on is installed.  The server side portion of these various services must be run on a Unix machine within the cell or, as shall be demonstrated, from a Windows NT machine with third party add-ons.

 

2.1.3 Intermediary servers

One additional method for integrating DOS/Windows 3.1 workstations, as well as Windows 95 or Windows NT workstations, into the DCE standard environment is through the use of intermediary servers.  Intermediary servers are programs which act as servers in one environment and clients in another, forwarding the requests they receive to servers in the final target environment.  In this way, these programs bridge two disparate environments.  For more detailed information, see Shirolkar [27].

An intermediary server strategy could be employed on a machine (e.g., a Unix workstation) which is a normal member of a DCE cell.  If this machine also supported a protocol that is accessible to typical PC machines (e.g., IPX or TCP/IP), it could function as an intermediary server.  That is, a program could be written that accepts requests via, for example, TCP/IP and then makes a corresponding call to a true DCE server application that actually services the request and returns information to the intermediary server.  The intermediary could then return the results to the client via the client’s understood protocol.

This system would allow PC clients to access specific DCE servers without any additional software.  However, it would require that a custom intermediary server be written for each server to which access was desired.  While this might be a very good solution if an organization required access to only one or a small number of DCE servers from their personal computers, the effort involved with writing many intermediary servers in the more general case might be deemed too great.

Sirish [28] proposes a variation on intermediary servers called application gateways.  An application gateway is a mechanism for redirecting the input/output of a client (or stand-alone) program.  This solution allows a PC to talk to an application gateway that is running on a member of a DCE cell, again via a protocol supported by both the PC and the DCE machine.  However, in this scenario, the PC is actually interoperating with a DCE client program.  The client program communicates as normal with the DCE server, but the user interface is remotely transported to the PC, essentially enabling the PC to function as a DCE client.

The primary drawback of such a solution is that it can only work with programs that use standard I/O mechanisms such as the stdio library.  Modern windowing user interfaces could conceivably be supported as well, but this would likely increase bandwidth requirements significantly.  Another disadvantage of this solution is that it requires recompilation of the client software, which may not be possible in some instances due to the lack of source code availability.

 

2.2 Microsoft Windows 95

In late 1995, Microsoft released the successor to Windows 3.x, dubbed Windows 95.  Windows 95 was a dramatic departure from Windows 3.x with regard to user interface, as well as some of its internal architecture.  Windows 9x refers to Windows 95 and its successors (Windows 98 has only recently been released at the time of this writing).  Windows 9x is largely a 32 bit operating system, while Windows 3.x is completely 16 bit.  In the Microsoft world, this means not only that Windows 9x supports 32 bit integers, but more importantly that it natively supports a set of API’s (Application Programming Interfaces) called Win32, as well as many advanced OS features such as threading.  Win32 is the basis for writing applications that run on both Windows 9x and Windows NT.

Although Windows 9x is dramatically more advanced than Windows 3.x, it remains focused on backward compatibility with DOS and Windows 3.x applications.  This means that much of Windows 9x retains 16 bit subsystems and that the designers of Windows 9x continue to choose compatibility when tradeoffs exist between support for legacy applications and robustness and/or security.  Microsoft has stated that Windows 9x will continue to support virtually all DOS and Windows 3.x applications, including “poorly behaved” games and other applications.  By committing to the support of these legacy applications, Microsoft is forced to allow applications to perform dangerous operations (such as, in some cases, writing to memory that is in the process space of another application) that may compromise the integrity of the entire OS session.

In terms of support for DCE applications, Windows 9x natively ships with support for RPC’s, but does not support any of the other DCE services.  Here again, as with Windows 3.x, a DCE developer porting an application to Windows 9x would come up against the lack of DCE services as well as the total lack of POSIX support.  An application written for even the most basic level of POSIX compliance does not typically compile under Windows 9x.  Again, a third party add-on such as Gradient’s products can somewhat improve this situation, but the developer then must rely on deployment of the third party product upon all target workstations (and must be prepared for the consequences of the associated expense).

As with DOS and Windows 3.x, there are currently no add-ons for Windows 9x which implement the server side of the various DCE services.  Therefore a Unix workstation or a Windows NT machine is required to provide the server side services within a DCE cell.

 

2.3 Microsoft Windows NT

Windows NT is Microsoft’s modern fully 32 bit operating system.  Unlike Windows 9x, which was developed from earlier Windows 3.x code, Windows NT was written from the ground up with the goal of being a secure and robust operating system.  Since its introduction, many features have been added to Windows NT and some code is now shared between the development teams at Microsoft, which work on Windows 9x and Windows NT respectively.  It has been noted in the press that sharing code with the Windows 9x team may tend to compromise the NT design goals of robustness and security.  Personal experience tends to validate this criticism.

Windows NT natively supports RPC’s in the same way that Windows 9x does.  The Microsoft implementation of RPC is compatible with DCE RPC, but is developed independently by Microsoft.  Windows NT does not ship with any DCE services beyond RPC.  However, Gradient and Digital Equipment Corporation both provide solutions that fully implement DCE client (clerk) services on Windows NT.  Windows NT can also be extended to provide the DCE server side services (CDS server,  DTS server,  DFS server, and Security server) via packages available from each of these vendors.

 

2.4 IBM OS/2 and Apple Macintosh

While the Microsoft family of operating systems dominate in terms of installed base (see Figure 2), there are still many installations which have large numbers of Apple Macintosh computers running their own proprietary “System” operating system (currently System 8).  Likewise, certain organizations have large numbers of IBM’s OS/2 operating systems deployed.

Currently, the Apple Macintosh may be integrated into the DCE world only through the DCE client extensions supplied by Gradient (see http://www.gradient.com/Products/Pc-dce/pcdce_front.htm).  Gradient’s kit supplies the same client or clerk side services, as do the analogous kits for Windows 3.x, Windows 9x, and Windows NT.  IBM’s OS/2 can be brought into the DCE world through either Gradient’s product (again, with the same features as those available on the Macintosh platform), or through IBM’s own DCE package (http://www.networking.ibm.com/dce/dceprod.html).  In addition, IBM has recently introduced a new product called Directory Systems Series (DSS; see http://www.software.ibm.com/is/sw-servers/directory/index.html) which provides the server side software for DCE on OS/2 servers (as well as other platforms for that matter).

2.5 OS choices conclusion

While Apple Macintosh computers and computers running IBM’s OS/2 are certainly relevant and important to certain environments, they have each essentially become niche players.  Therefore, these two operating systems are excluded from further discussion.

A similar case can be made that Microsoft DOS and Microsoft Windows 3.x systems are rapidly fading into the past and should not be considered further either.  Though this is true to some extent, there remain vast numbers (see Figure 2) of DOS and Windows 3.x clients deployed throughout business and academia.  It seems premature to discard consideration of these platforms entirely.  Though neither can be full players in the DCE world due to their inherent lack of capabilities (e.g., true threading), they can, in many cases, be used for client-side solutions which leverage the more mature capabilities available on servers from other environments.  For example, a single-threaded DOS DCE client application may be completely sufficient to access and utilize a multi-threaded DCE server application running on a Windows NT system or a Unix system.

In the next section the tools and environment needed to implement a DCE application on each of the selected target platforms will be explored.  Each of the DOS/Windows 3.x, Windows 9.x, and Windows NT platforms has unique requirements and can benefit from specific additional third party software in order to function as part of a DCE cell.


3. What You Need

 

This chapter provides a minimal list of software and tools that are required to create an RPC enabled application.  Such applications are not fully DCE enabled, lacking security, name services, and distributed file system support.  However, applications written with these minimal standard Microsoft tools can be distributed without a need for expensive and cumbersome third party software, and are able to interoperate with standard DCE applications through RPC’s.

One alternative to forgoing CDS capability that can augment this approach is to install the Name Service Interface Daemon (NSID).  NSID can be installed on a CDS capable client (such as an NT workstation with Digital DCE installed).  NSID can then forward Microsoft RPC calls to the real CDS in the cell.  NSID can thus partially obviate the need for CDS support on all client workstations.  However, all Microsoft RPC clients in the cell will have to be configured to access the specific machine with NSID installed, and this can present both configuration and load-balancing issues (i.e., the machine with NSID installed may be overtaxed if many clients utilize it).  This problem can be mitigated by deploying multiple instances of NSID to balance the load, but the lack of any centralized capability for configuring clients could prove problematic.

 

3.1 Supported protocol stacks

DCE is able to sit atop a long list of supported wire protocols.  Wire protocols, or protocol stacks in Microsoft parlance, are software modules which essentially implement the Data Link Layer, the Network Layer, and the Transport Layer of the Open Systems Interconnection (OSI) Reference model.  However, in Microsoft environments, DCE must sit atop a protocol stack that is specifically designed to support DCE.  For DOS and Windows 3.x, this generally means a stack called the Microsoft Remote Procedure Call 16 Bit Run-time (Microsoft RPC RT16).  Despite its name, Microsoft RPC RT16 provides not only the actual RPC run-time modules, but also a wide selection of underlying protocol stacks.  These include UDP/IP, TCP/IP, Named Pipes, Netbios, DEC Net, SPX, and IPX, all for use under both Windows 3.x and MS DOS.

Microsoft RPC RT16 is available from Microsoft as part of the Windows 32 SDK which is included in the Microsoft Developer Network Library (MSDN).  MSDN is a set of software and reference material available via an annual subscription from Microsoft.  The January 1998 edition of MSDN provides the RPC RT16 on disk number 7 in the directory \MSTOOLS\RPC_RT16.  Windows for Workgroups 3.11 came with a protocol stack that is essentially the same as RPC RT16, and so does not require installation of this additional software.  Installations using Microsoft LAN Manager also natively support the RPC RT16, and do not require additional software.

Other protocol stacks which support Windows Sockets may also function correctly as RPC transports for DOS and Windows 3.x environments, but there are no guarantees.  Windows 9x and Windows NT each come equipped with native protocol stacks that support Microsoft’s RPC, as well as the necessary RPC run-time.  No additional software is required.

 

3.2 Development kits

In order to use RPC’s (the base feature that is available as a standard for Microsoft operating systems), a developer of software needs the appropriate software development kit (SDK).  This SDK consists of the appropriate C language header files, libraries, and binary tools needed to create an RPC enabled application.  In the case of DOS and Windows 3.x, this is provided as an add-on called the Microsoft Remote Procedure Call SDK (RPC SDK).  Like the RPC RT16, the RPC SDK is available as part of MSDN. In the January 1998 edition, RPC SDK is included on disk number 7 under the \MSTOOLS\RPC_SDK subdirectory.

For 32 bit environments (i.e., Windows 9.x and Windows NT), the requisite header files, libraries, and tools are available as a standard part of Microsoft’s C compiler.  The current version at the time of this writing is Visual C++ version 5.0 (VC 5).  No additional software is required if a standard VC 5 installation is used.  Non-Microsoft compilers are supported for Win32 if they can link to standard Microsoft libraries.  The requisite libraries are also included in MSDN and called the Win32 SDK.  The Win32 SDK is on disk number 7 under the \MSTOOLS subdirectory in the January 1998 edition of MSDN.

 

3.3 Hardware

Apart from a standard IBM compatible PC, the main hardware requirement to utilize RPC’s is an NDIS compliant network card.  Most all network cards currently available on the market come with NDIS drivers, and so hardware is typically not an issue.

            As is the goal of DCE, the types of network card and network topology are not at issue.  Token ring, Ethernet, and other topologies that support NDIS are transparently supported.

 

3.4 Summary of what you need

By installing the appropriate protocol stack and the requisite RPC run-time code on an IBM standard PC with a network card that supports NDIS drivers, one has all that is needed to run a simple application that can use RPC’s.  Such applications can interoperate with standard DCE applications running on any DCE compliant machine, provided that only RPC facilities are needed.  If security services, name services, threading, or any other DCE service is required on the client PC, additional software is needed.  To develop limited applications such as this, one also needs the appropriate SDK software.

For some simple applications, these requirements are quite sufficient.  Nonetheless, the developer of such an application must be clear that the target platform is, in fact, a PC.  The developer must not assume when writing code that POSIX support is available, and must not rely on any DCE service, save RPC.  This is fine for an application that simply makes a call to be executed on a remote machine.  However, most real world applications certainly require security, and likely require name space service.  In addition, the great strength of DCE is that it promises to free developers from making assumptions about platforms.  This makes the basic solution available from Microsoft rather unsatisfying.  A more complete solution must include some third party software to add DCE features and services that are not available from Microsoft.

Figure 4: Summary Of Requirements For RPC On Microsoft Platforms


 



4. Third Party Tools

 

In this chapter, software that simplifies and improves the integration of personal computers into DCE is explored.  This includes tools provided by third party companies that add to the native capabilities of PC operating systems by adding support for additional DCE services, or enhancing the environment of developers seeking to write DCE compatible code.

 

4.1 Digital DCE for Windows NT and Windows 95

Digital Equipment Corporation (DEC; now a subsidiary of Compaq Computer Corporation) offers a full implementation of DCE for Windows NT and Windows 95 (see http://www.dec.com/dce/).  Products are available both for the client (or clerk) side and for the server side of DCE for Windows NT, and for the client side for Windows 95.  IBM offers the same set of products rebranded under the IBM name.

For this project, version 1.1 of the client side product on the Windows NT platform was tested.  The product comes in two parts.  The first is called “Digital DCE for Windows NT Runtime”, and must be deployed on any NT workstation that is to be part of a standard DCE cell.  The second part is called “Digital DCE for Windows NT ADK”, meaning the “Application Development Kit”.  Those who wish to write (as opposed to use) DCE applications on NT require this part.  It includes the needed binary tools (e.g., the IDL compiler) as well as the header files and libraries needed to create a full-fledged DCE application.

Digital DCE for Windows NT includes fully DCE-compliant RPC (though still sitting atop Microsoft’s implementation of RPC rather than the Open Group source), POSIX threads, Security Client, CDS Clerk, Name Service Interface Daemon (NSID), and Distributed Time Service Clerk (DTS).  Additional packages are available to provide DCE Security Server and CDS Server on the NT platform.  With the runtime product installed on NT, a workstation was successfully configured as a normal DCE machine within a University of Missouri campus DCE cell, even though the NT workstation was initially located in the Datastorm Technologies offices across town from the University campus.

Version 1.1 of Digital DCE was designed to run on Windows NT 3.51.  For this project, the software was deployed on Windows NT 4.0 as well.  However, version 1.1 seems to require a dynamic link library (DLL) which was only installed under Windows NT 3.51.  When installing the product on NT 4.0, it is necessary to copy RPCDCE4.DLL into the \WINNT\SYSTEM32 directory before applications compiled with the ADK will run.  RPCDCE4.DLL ships with Windows NT 3.5.  Another difficulty with version 1.1, is the necessity of cell administrator security to install the product.  Digital claims that this will not be necessary for the new “Local Client” option in version 2.0 (see http://www.dec.com/dce/products/v20ntwp.htm), which incidentally adds support for C++ applications.  Since version 2.0 is designed to run on NT 4.0, it seems likely that the dependency on RPCDCE4.DLL will also be removed.

As mentioned, Digital also provides a client side DCE package for Windows 95 (see http://www.dec.com/dce/dcefiles/win95.htm).  This has not been tested as a part of this project, but will likely have some of the same advantages and disadvantages of the NT product (e.g., porting “normal” DCE applications that assume full POSIX compliance will continue to be a challenge).  There is no Security Server or CDS Server module available for Windows 95, so Windows 95 DCE installations require either a Unix machine in the cell to provide these services or a Windows NT machine with such modules installed.

 

4.2 Gradient’s PC/DCE

Like Digital’s offering, Gradient provides DCE software that has been ported from the standard OSF DCE source code to PC environments (see http://www.gradient.com/Products/Pc-dce/pcdce_front.htm).  Gradient offers runtime and ADK modules for Windows NT and Windows 95, as well as Security Server and CDS Server modules for NT.  Gradient also offers runtime and ADK modules for Windows 3.1 and Apple Macintosh platforms.

Gradient’s products are available for testing through a free limited-time download (see http://www.gradient.com/Products/evals/evals.htm).  However, this program was not available in time to allow testing on Gradient’s platform.  Previously, Gradient’s software was not available for free evaluations and the cost of procuring the software was deemed prohibitive.  Nonetheless, since Gradient’s products are based on OSF source code, it seems likely that they may be a very viable alternative to Digital’s products.

 

4.3 Hewlett-Packard OODCE

OODCE is a set of C++ classes layered on top of the standard DCE API’s.  The goal is to simplify DCE development and bring it more naturally into the C++/Object-Oriented world.  However, OODCE is currently a proprietary extension to DCE available only for Hewlett-Packard’s HP/9000 Unix platform (see http://www.hp.com/gsy/3b4.html).  While applications written in OODCE are interoperable with traditional C based DCE applications, the code itself is non-portable.

Although OODCE may allow developers in a purely HP/9000 environment to write DCE code more quickly and reliably, the sacrifice of true cross-platform coding seems too great.  As concepts from OODCE make their way into the OSF DCE standard, it will be appropriate to take advantage of them.  However, until then, it may be best to ignore this proprietary solution.

 


5. Porting An Existing OSF DCE Application to Microsoft Platforms (BINOP)

 

BINOP is a program written by Prof. Gordon K. Springer at the University of Missouri-Columbia to demonstrate DCE remote procedure calls.  The BINOP client module communicates with BINOP servers that are registered in the DCE namespace by issuing calls to them to do additions and subtractions.  BINOP is composed of a demonstration shell (BINOPDEMO), a worker client (BINOPC), a statistics gathering client (BINOPST), a help-providing client (BINOPHLP), and a server (BINOPS).  While the actual work performed by BINOP is trivial, the program serves to demonstrate RPC’s, the utility of the CDS, strategies for finding servers outside the local cell, and the client-per-thread server strategy.

BINOP can be built for DEC Alpha, Mips, Cray, HP 9000, IBM RS6000, and IBM mainframe platforms.  It was written with standard DCE platforms in mind as the target, presuming that most standard Unix facilities are also available.  This project sought to make a BINOP build and run on Microsoft platforms.  To that end, the results are available in Appendix A: BINOP Source Code.  As will be noted, there are several ways to build and use BINOP on Microsoft platforms, each with various tradeoffs in terms of features, portability, and requirements.  In the end, BINOP was able to interoperate with standard DCE BINOP servers using a DOS/Windows 3.x client and with a Win32 client.  Using Digital DCE for Windows NT, it was also possible to setup a BINOP server on the NT platform that could be accessed from any other DCE platform client.

 

5.1 Straight Microsoft

The first step in porting BINOP to Microsoft platforms was to try to make BINOP as fully functional as possible using only the native Microsoft tools available.  This meant that it should be possible to build BINOP with only Visual C++ installed on Win32 platforms, and with only Visual C++ and the RPC SDK installed on DOS and Windows 3.x platforms.  Of course, where BINOP uses DCE or Unix facilities that are unavailable on Microsoft platforms, it is necessary to either write workarounds or simply live with the loss of functionality.

This goal was accomplished only for the BINOPC program.  BINOPC is the worker executable that actually makes the addition and subtraction RPC’s.  Even here, however there was a need to conditionally compile portions of the code.  For example, the file MAKEPASS.C includes PTHREAD.H.  This is a support file for POSIX threads.  Since Microsoft platforms do not directly support POSIX threads, this header file had to be conditionally excluded (based on the Win32RAW macro, which was used to indicate a Microsoft native only compilation).  In addition, the Microsoft DCE compatibility file DCEPORT.H had to be included since Microsoft changed the names and calling conventions of many standard DCE API’s in their implementation of the RPC (e.g., rpc_binding_vector_free() becomes RpcBindingVectorFree()).

Several other compromises were necessary, including conditionally removing the error handling for the RPC’s in MAKEPASS.C since the TRY-CATCH syntax has been changed under current Microsoft compilers.  TRY, CATCH, CATCH_ALL, and ENDTRY are macros used for structured exception handling in the C and C++ languages.  While Microsoft provides a header file called DCEPORT.H to map these macros (as well as make numerous other remappings) to appropriate Microsoft syntax, the mappings currently appear to be outdated.

Figure 5 shows a successful trial run of the BINOPC client compiled using the WIN32RAW target (and thereby lacking the error handling mentioned).  Notice that the program completes the series of additions and subtractions successfully.  This trial was performed on a Windows NT 4.0 workstation that was interoperating with a BINOPS server, running on a Digital Unix machine called “Condor” on the University of Missouri campus.

Figure 5: Successful WIN32RAW Binopc Run.

 

Figure 6 shows the same BINOPC client, again running on the same Windows NT machine and communicating with the same Digital Unix machine.  After the program printed the result “38”, a communication failure was simulated by disconnecting Windows NT Dial-up Networking (which was being used to achieve Internet connectivity).  Figure 7 shows the error dialog displayed by Windows NT when this communication error occurred.  Clearly, this is not a desirable way to handle such a fault.

Figure 6: WIN32RAW Binopc Run With Communication Error.

Figure 7: Windows NT OS Error Dialog.

           

Figure 8 shows BINOPC on the same Windows NT workstation, but recompiled using the WIN32 target (discussed in Section 5.2).  Again, the program is communicating with the “Condor” BINOPS server, and again a communications error is simulated.  This time, however, the error handling code is in place, and the program gracefully degrades by reporting the error.

Figure 8: WIN32 Binopc Run With Communication Error.

 

An effort was made to port the remainder of the BINOP code to the “Win32RAW” platform.  However, it eventually seemed clear that the amount of code necessary to accomplish this without use of third party software was prohibitive.  For example, in order to port the server code properly, it would be necessary to write a custom implementation of POSIX threads.  Since DOS and Windows 3.x do not support true threads, this seemed beyond reason.  Although mapping POSIX threads to Win32 threads would certainly have been possible, it was more sensible to rely on a third party product for POSIX threads as well as many other standard DCE features.

 

5.2 Full DCE

After creating the raw build of BINOP, a build of the BINOP source that relied on the Digital DCE for Windows NT ADK for compilation and on the Digital DCE for Windows NT Runtime for execution of the resultant binaries was created.  As can be seen from the source in Appendix A, this build is termed the Win32 build.  The goal for this build was to fully port BINOP and be able to run both clients and servers on a Windows NT platform.  This goal assumes that the Digital DCE for Windows NT Runtime is installed and that the host machine is properly configured as part of a DCE cell.  That is, it is assumed that there is a machine in the cell providing the CDS server and security server and that the host is able to access them in standard DCE fashion.  No assumption is made with regard to supported wire protocols, though tests for this project focused on TCP/IP and UDP/IP since these protocols are available on nearly every platform.

 

5.2.1 Porting difficulties

Again, the porting process uncovered serious incompatibilities between standard DCE platforms and the Microsoft platforms that had to be worked around, even with the additional Digital software.  Many problems were sufficiently subtle that long hours of pouring over the code were necessary to discover their source.  Even small differences can cause code to fail.  For example, code that attempts to parse a file path must look for a backslash (“\”) on Microsoft platforms and a forward slash (“/”) on Unix platforms.  This was dealt with in BINOPS.C.  Also in BINOPS.C, it was necessary to change a function (rindex()) that was not strictly POSIX compliant to its POSIX equivalent (strrchr()).

Any code that deals directly with file systems or file permissions also tends to fail.  One such function is the umask() function which is unsupported on Microsoft platforms.  There were many other incompatibilities that were essentially the result of NT’s lack of POSIX compliance in its Win32 subsystem or minor variances from POSIX in the BINOP code.  These incompatibilities are identified throughout the code in Appendix A where conditional compilation constructs based upon the Win32 macro are used.

Several other incompatibility challenges arose due to the fact that even using Digital DCE for Windows NT, one is still left using Microsoft’s implementation of RPC’s and the RPC set of API’s.  For example, in BINOPST.C, special code was added to deal with a difference under the Microsoft implementation of the rpc_mgmt_inq_stats() function.  Here, the universal unique identifier (UUID) of the server is required for this API, rather than the client as is the case under standard DCE.  Since Gradient’s product is reputed to use OSF source even for RPC’s, it may not suffer from some of the incompatibilities of Digital’s product.  This was not tested, however.

Perhaps the most difficult compatibility problem to track down was a difference in Microsoft’s implementation of a DCE interface-specification.  An interface-specification is an opaque data structure containing information the RPC run-time library uses to communicate with the stubs.  A stub is a piece of code created by an IDL compiler, which acts as a surrogate for a function.  A stub communicates with the RPC runtime in order to contact remote processes, marshals and/or unmarshals parameters, and then calls the actual worker function that it represents.  Under standard DCE, the IDL compiler-generated IDL_ifspec variable is a rpc_if_rep_t structure, while under Microsoft it is a RPC_CLIENT_INTERFACE structure.  Admittedly, these are considered to be “opaque” structures that are not strictly supposed to be used by application programs.  However, the server finding module used by BINOP (FINDSRVS) utilizes the interface-specification as a convenient way to pass UUID’s to the finding server, and this technique works fine on all standard DCE platforms.  Since Microsoft’s structure is dramatically different in format than the standard structure used by DCE, it was necessary to create a temporary structure and use it to reformat the information contained in Microsoft’s structure under Win32.  It should be noted that incompatibilities between Microsoft RPC and DCE RPC were almost completely undocumented, prior to the publication of this document.  Many months were spent discovering the causes of problems such as the interface-specification incompatibility.

The build process itself also suffered from platform incompatibilities.  For example, the syntax of the standard Unix MAKE utility is slightly different than the Microsoft NMAKE utility.  The Unix makefile’s for BINOP contained lines with the ‘date’ macro, which simply does not evaluate under Microsoft’s NMAKE (under Unix it prints the current date).  For this project, a proprietary utility called TM that echoes the current time and date was substituted.    Other incompatibilities included the lack of the Unix CHMOD utility on Microsoft platforms and differing syntax for dealing with library files.

 

5.2.2 Platform advantages

While there were limitations and difficulties in moving BINOP to the Win32 platform, there were also opportunities to take advantage of platform specific strengths and features.  Since there was no direct concept of a Unix daemon process under Win32, the ability for the BINOP server to run as a Win32 service was added.  A service is a user-interface-less program that can be controlled via the Microsoft Control Panel Service applet.  This applet allows the user to start, stop, pause, and control the automatic start-up options for the service.  Some Microsoft-supplied code was modified and included in the project, in order to turn BINOPS into a service.  However, it should be noted that it was a significant task even with the Microsoft code to turn BINOPS into a service, since BINOPS was designed to execute as a Unix daemon process.  Some instability was encountered when running the server for long periods of time as a service, but this was not conclusively proven to be related to the service code.

For the future, it would be sensible to take advantage of the rich user interface features of the Win32 platform.  It would be possible to further separate the user interface portions of BINOP from the worker portions.  This would facilitate replacing the user interface modules in a platform specific manner, allowing Win32 in particular to have an excellent user interface.  This was not done, but would be a relatively straightforward extension of the porting process.

 

5.2.3 General challenges

In addition to the direct issues involved with porting BINOP to the Win32 platform, several issues that are general to setting up and using DCE in the real world were encountered during the project.  Since some of the effort took place on the University of Missouri campus and some took place in a private business (Datastorm Technologies, Inc. – now the Columbia, Missouri site for Quarterdeck Corporation), several problems became apparent that might not otherwise surface in a project that was conducted in one physical locale.  For example, it was found that the Distributed Time Service (DTS) was often generating errors due to occasional extended lags in routing packets between the two sites (although the two sites were located within the same city, packets often went across the country, taking as many as 20 hops, before getting to the other site!).

Toward the end of the project, Quarterdeck installed a “firewall”, ostensibly to protect its network from unwanted outside influences.  This firewall was configured to allow certain of the most popular types of TCP/IP traffic to pass through it (e.g., HTTP, FTP, etc.).  The firewall was not, however, configured to allow DCE traffic to pass through it.  This effectively ended the ability to do multi-site testing for this project.  Client-side testing was largely possible through dial-up TCP/IP (PPP), but since DCE requires a static IP address endpoint for actual membership in a cell, server side testing on the dialing host was not possible.  As DCE becomes more prevalent in private businesses, firewalls must evolve to support the multi-protocol and multi-port nature of DCE.


 6. The Future (Is Sooner Than You Think)

 

6.1 DCOM

DCOM is Microsoft’s Distributed Component Object Model.  DCOM allows an object to be utilized by a client program without regard to whether the component is actually executing on the local machine or across a network.  It is based on the Component Object Model (COM), which is Microsoft’s standard for creating reusable components   (see http://www.microsoft.com/com/ and the seminal Inside OLE 2nd Edition by Kraig Brockschmidt, Microsoft Press, 1995).  While COM itself is not concerned with distributed computing, Microsoft has built COM on top of an Interface Definition Language (IDL) scheme that is very similar to the IDL facilities in both DCE and CORBA (see section 6.2 for a discussion of CORBA).  The object methods in the COM IDL files can have attributes that correspond to DCE RPC’s (e.g., [in], [out], etc.).

With Microsoft’s introduction of DCOM (see the DCOM specification: (http://www.microsoft.com/oledev/olecom/draft-brown-dcom-v1-spec-01.txt, which is an Internet Engineering Task Force (IETF) working document) in Windows NT 4.0, standard COM objects can be “remoted”.  That is, Microsoft provides marshaling code via their IDL compiler, the Microsoft Interface Definition Language compiler (MIDL), that allows methods of defined objects to execute on a remote machine.  In fact, this remoting mechanism is Microsoft’s RPC!  This means that standard RPC code can be written to take advantage of services provided by DCOM objects, with the proviso that RPC code would have to deal with C++ name mangling (see Glossary entry on name mangling) and with special DCOM protocol concerns, noted hereafter.  In an effort to make DCOM more open, Microsoft has entered into a project with the Open Group to make this technology available on other platforms (see http://www.activex.org/announce/ActiveX_Core_Technologies.htm).


Figure 9: DCOM Architecture

 

Adapted and simplified from “C++ Report” January 1998, p. 26 Patterns++ column.

 

Figure 9 shows a simplified view of the DCOM architecture.  Essentially, Microsoft has added an infrastructure that transparently creates and manages objects on remote machines, so the writer of the client application does not need to know anything about RPC’s.  For example, the author of the client application does not need to know whether or not the server on the remote machine is running.  The application simply creates and uses the object, and DCOM takes care of actually creating and shutting down the server object as necessary.

It is worth noting, however, that Microsoft has not currently defined a scheme for object discovery.  That is, DCOM does not have anything akin to DCE’s Cell Directory Service.  A client DCOM application (or at least a field in the client machine’s registry database) does need to know on what machine the remote object is executing!  Microsoft plans to correct this problem in the future through the proliferation of their Active Directory Services (see http://www.microsoft.com/ntserver/guide/activedirectory.asp).

Microsoft hopes that DCOM will become a cross platform standard that essentially replaces DCE.  In partnership with Microsoft, Software AG is currently porting DCOM to various non-Microsoft platforms, including IBM MVS, Sun Solaris, Digital Unix, and several others (see http://www.sagus.com/Prod-i~1/Net-comp/dcom/index.htm).

 

6.1.1 DCOM/DCE interoperability mechanics

The following is a brief discussion of the mechanics that allow DCOM to sit atop DCE RPC.  Note that much of the code to implement DCOM’s scheme is automatically generated by the MIDL compiler, and is not typically a concern for a developer merely wishing to utilize DCOM.  For complete details of the DCOM protocols see Microsoft [17], and Stal [29].

Each computer supporting DCOM provides a service known as the “Object Exporter”.  The Object Exporter communicates via standard DCE RPC on well-known endpoints (protocol specific identifiers unique to a given server process, such as a TCP/IP port number), and its function is very similar to the standard DCE endpoint mapper.  The DCE endpoint mapper is a service that runs on any workstation having DCE servers, and in most implementations is simply a component of the RPC daemon.  The service tracks the endpoints the servers on that node are currently using, and communicates this information to the RPC runtime of clients wishing to use a given server.  In fact, Microsoft has proposed that the special endpoints used by the Object Exporter to talk to the runtime be the same as that used by the DCE endpoint mapper.

The Object Exporter supports several remotely callable procedures, bound up in what Microsoft refers to as the IObjectExporter interface.  This name is somewhat misleading because it seems to imply that IObjectExporter is a COM interface, when in fact it is not.  Actually, IObjectExporter is merely a collection of the following RPC’s implemented on every computer that supports DCOM: ResolveOxid(), SimplePing(), and ComplexPing().

Every DCOM object provided by a server must support the IRemUnknown interface.  Unlike IObjectExporter, this is a true COM interface.  Its methods are similar to those in the standard COM IUnknown interface with the “Rem” prefix added: RemQueryInterface(), RemAddRef(), and RemRelease().

By implementing these interfaces, and dealing with standard C++ name mangling, any platform should be able to support DCOM.  At least, of course, until Microsoft changes the rules!  It is worth noting that Microsoft hopes to make DCOM into a platform independent standard, although history tells us that Microsoft generally respects only those standards over which it has control.

 

6.2 CORBA

The Common Object Request Broker Architecture (CORBA) is the Object Management Group’s (OMG) (see http://www.omg.org/corba/) answer to the problems of distributed computing.  While similar to DCE and DCOM in that it uses an Interface Definition Language (IDL) to specify remote object procedures and methods, it does not build directly upon standard RPC’s.  The designers of CORBA consider the wire protocol an implementation detail (while RPC specifies a layer above the wire protocol and allows various wire protocols to “plug in” to it).  The strength of this approach is that any protocol can potentially be used by an implementation of a CORBA Object Request Broker (ORB).  The weakness, of course, is that there are no clear means for ORB’s using different wire protocols to interoperate.


Figure 10: OMG’s CORBA

Adapted and simplified from “C++ Report” January 1998, p. 26 Patterns++ column.

 

Figure 10 is a bird’s eye view of OMG’s flexible CORBA architecture.  Note that a TCP socket is specified as the transport for the CORBA remote function.  This is actually true specifically for the Internet Inter-ORB Protocol (IIOP), which is a particular implementation of an ORB protocol that is commonly implemented by vendors of various ORB’s.  If this ORB protocol is implemented on all ORB’s involved in a given communication session, then the ORB’s can interoperate.  Again, a given vendor’s ORB may use any wire protocol, but most will also support IIOP in order to work in multi-vendor environments. 

Like DCE, CORBA is not a standard part of common personal computer environments.  In order to deploy CORBA clients and servers on PC’s, it is necessary to install additional third party software.  For example, Digital Equipment Corporation sells a product called Object Broker, which includes PC desktop connectivity with CORBA (see http://www.digital.com/objectbroker/).  The product accomplishes this by mapping CORBA functionality to Microsoft OLE/COM for use on the PC.  The Distributed System Object Model (DSOM), which is IBM’s CORBA ORB, is also available for Microsoft Windows platforms, as well as IBM OS/2 (see http://www.software.ibm.com/ad/somobjects/).

 

6.3 WWW and DCE

The World Wide Web (WWW or Web) has become a popular tool for nearly every networked computer.  The Web was initially a medium for the exchange of academic information, and soon grew to provide corporate and recreational information as well.  However, recently, businesses have begun to use the Web to truly conduct business, through electronic commerce, electronic brokerage services, and connection of geographically diverse corporate Intranets.  With this change has come a need for security and authentication.  Many businesses still resist connecting their internal networks to the Internet, feeling that these security issues are inadequately addressed.

The organization responsible for the continued development of the DCE standard (The Open Group) has supported the “DCE Web Project” in an attempt to resolve these concerns (see http://www.camb.opengroup.org/www/dceweb/ and http://www.camb.opengroup.org/RI/www/prism/index.html).  The initial strategy of the project is to provide what is called a Secure Local Proxy (SLP) for browsers within the corporate Intranet.  This means that browsers on desktops within a corporation (presumably behind a firewall) can reach a proxy (installed on that client machine) through standard browser means (i.e., the HTTP protocol).  The proxy may then access secure information via DCE connection to other internal resources, allowing for standard DCE encryption and authentication services, as well as the ability to use CDS for discovering relevant servers (and thereby potentially providing such services as load-balancing).  This scheme allows a corporation to internally publish sensitive or secured information on the “DCE Web”, and yet allow users to access this information through the standard browsers to which they’ve become accustomed.

An auxiliary strategy for the project is to provide a Security Domain Gateway (SDG), accessible through the standard Secure Sockets Layer (SSL) protocol (which is now available to most popular web browsers).  Here, no installation of software on client machines is necessary.  SSL is employed to provide security and authentication from the client to the SDG, and the SDG uses a temporary DCE identity (derived from the SSL properties of the client) to access secure DCE resources.  Like the SLP strategy, the SDG can also take advantage of other DCE services such as CDS.  Organizations can determine which groups of users can access a given document through standard DCE Access Control Lists (ACL).  This solution is essentially an intermediary server for web browser applications (see Section 2.1.3).

Both the SLP and the SDG can access the multi-protocol DCE Web Server.  This third component allows corporations to publish given documents through standard Web methods (e.g., HTTP), but to also publish security sensitive documents as available only through secure DCE methods, invoked by either the SLP or the SDG.  Figure 11, following, illustrates the general architecture of the complete DCE Web project.

Figure 11: DCE-Web

The Open Software Group provided this clip art.

 

The Open Software Group’s DCE Web project is a viable alternative to true DCE client software for organizations primarily interested in deploying DCE security on their personal computers.  While this method of integrating PC’s into DCE does not allow standard DCE software to run on client machines, it does provide a middle ground that may be very useful for some organizations.


7. Conclusion

 

DCE can solve many of the inherent problems of distributed computing.  It allows heterogeneous computers to interoperate across a wide variety of network topologies and protocols.  It allows software developers to write traditional functionally-decomposed code with little consideration for which functions are executing locally and which ones are actually being executed on a remote system.  DCE improves the use of network bandwidth by allowing developers to deploy computing functions in close physical proximity to data resources, thus dramatically reducing the volume of data that must be transmitted across the network.

However, DCE is not yet fully the seamless solution that is advertised.  This is largely due to incompatibilities between standard DCE implementations and partial implementations of DCE contained in the widely deployed Microsoft family of operating systems for personal computers.  This problem can be viewed as falling under the category of accidental complexity (as opposed to inherent complexity), since it has essentially been introduced by Microsoft’s failure to adhere to the DCE standard.  Nonetheless, few software developers can afford to ignore the Microsoft family of platforms since they are nearly ubiquitous in most business and academic settings.  Hopefully, this thesis can be used as a guide to choose among the wide variety of possible methods to overcome these problems.

In addition to accidental complexities, there are inherent complexities in distributed computing that are not addressed by DCE.  Microsoft’s DCOM essentially recasts DCE in an object-oriented paradigm, but it does not truly add much in the way of solving several major challenges.  The promise of distributed computing is decoupling: decoupling code from its components’ execution contexts (as DCE does), decoupling compile-time interfaces from their run-time implementations (as COM does and DCE can be made to do), and someday decoupling compile-time semantic need from run-time syntax (which is currently not done).

The last of these is an item for future research.  It seems that DCOM, through OLE automation, has gone far enough to provide syntactic information for using distributed objects.  This is accomplished through “type libraries” which provide binary representations of syntactic information.  For example, it is possible to write a program that can construct calls to DCOM objects about which the program had no knowledge at compile time.  So, a program might be able to call SpellCheck(“string1”, “string2”).  However, there is no method in DCOM for the program to discern the meaning of the function or its arguments.

A program might discover an object out somewhere in the Internet which provides this SpellCheck() function.  It might discover that the function takes two arguments, each of which is a string.  It might even discover that the names of the arguments are “StringToBeChecked” and “DictionaryFileName”.  However, the program has no way of determining the meaning or semantic information behind these parameter names.

In the end, DCE is an excellent solution for many of the problems of distributed computing.  However, it is not a panacea.  Distributed computing, by its very nature, intensifies the difficulties inherent in writing cross platform applications, and DCE itself has no answer for this.  DCE does not solve the problems of differing operating system capabilities (e.g., lack of POSIX support), nor does it guarantee that every platform will implement all of its features.  Nonetheless, DCE can help make distributed computing less effort intensive for programmers, and it can help to make cross platform applications possible if some care is taken by the developer.  Even Microsoft environments with their legendary lax adherence to standards can be brought into the DCE fold and made to interoperate with other DCE systems.

This thesis has demonstrated that a DCE application can be ported to prevalent PC environments and that such an application can easily interoperate with a DCE cell containing a variety of heterogeneous systems.  Although PC environments may natively lack full DCE compliance, third party solutions along with some custom work-arounds can be employed to provide nearly complete interoperation.  This author has learned a great deal about porting applications between Unix and PC platforms, DCE’s influence and relevance to other distributed technologies such as DCOM and CORBA, and particularly about the tendency of a certain large software company to create standards rather than adhere to them.  The author has tried to pass on this knowledge, through this document, that others may benefit should they find themselves on this same path.


 

Glossary

 

API – Application Programming Interface.

Bandwidth – The capacity of a network to transport data, typically measured in mega-bits per second.

Big-endian/little-endian – Data storage techniques.  Little-endian systems place the least significant byte first and the most significant byte last.  Big-endian orders bytes in the opposite manner.  These storage schemes are respectively employed on various processors.

Client/Server – A style of programming in which code is distributed between clients and servers.  Typically, client applications present and retrieve information from users while server applications perform calculations and retrieve data.  It is often useful to locate servers “near” to their data sources (i.e., on the same machine or a short number of network hops away from the data).

DCE – Distributed Computing Environment.  This is a software architecture for distributed applications developed by OSF.

Endpoint – A protocol specific identifier (e.g., a TCP/IP port number), unique to a given DCE server process.  Upon obtaining an endpoint, a DCE client may use it to directly communicate with a DCE server.

IDL – Interface Definition Language.  This is a language used to specify how parameters are passed between entities in a distributed application.  It is converted by an IDL compiler to either C or C++.  The language specifies interfaces or functions that are to be deployed remotely.  It includes special keywords to indicate how parameters are to be transported across the network, such as [in] or [out].

Marshaling – The process of turning data structures into a bit-stream representation suitable for transmission across a network.

MSDN – Microsoft Developer Network.  This is a subscription service available from Microsoft which provides documentation and software development kits for Microsoft platforms.

Name Mangling - Name mangling or name decoration is the practice of most C++ compilers of creating unique names for method entry points by adding the class name and some special characters to represent the parameters.  For example, int MyClass::MyFunc(int I) might be exported as MyFunc@MyClass@i.  This guarantees that each method has a unique entry point name, so it is legal to have additional functions with the same name such as MyClass::MyFunc(char c).  The specific scheme used to create mangled names is an implementation detail for each compiler.  There is no standard.

RPC – Remote Procedure Call.  This is the foundation upon which DCE is built.  Microsoft’s version of RPC is binary compatible with DCE, but is not based on the same source code.

Stub - A piece of code created by an IDL compiler, which acts as a surrogate for a function.  A stub communicates with the RPC runtime in order to contact remote processes, marshals and/or unmarshals parameters, and then calls the actual worker function that it represents.

UUID – Universally Unique Identifier.  This is a key value that is guaranteed to be unique.  It is also referred to as a GUID or Globally Unique Identifier by Microsoft.

Win32 – The API used to write programs that can run on either Windows 9x or Windows NT.

Windows 3.x – Any of the 16 bit family of Microsoft Windows products, including Windows 3.0, Windows 3.1, Windows 3.11, and Windows for Workgroups 3.11.

Windows 9x – Any of the 32 bit “compatibility” Microsoft Windows products, including Windows 95, Windows 98, and beyond.  These are referred to by the term “compatibility” in order to distinguish them as products designed to maintain compatibility with older products (DOS applications, Windows 3.x applications, etc.).  This differentiates this group from Windows NT.

Windows NT – Any version of Microsoft Windows NT, including Windows NT 3.5, Windows NT 4.0, Windows NT 5.0, and beyond.  These products were designed to compete with Unix and other robust operating systems used for “mission critical” applications.  Dave Cutler, who was instrumental in developing the VMS operating system while at Digital Equipment Corporation, led the development of Windows NT.


 

References

 

1.      Active Group World Wide Web site, http://www.activex.org.

2.      Don Box, Essential COM, Addison Wesley Longman, Inc., 1998.

3.      Chappell and Associates Report, http://www.camb.opengroup.org/dce/3rd-party/ChapRpt1.html.

4.      Digital Equipment Corporation, “Digital Distributed Computing Environment (DCE) for Windows NT”, in the Microsoft Developer Network under Backgrounder\Platform Articles\Networking, October 1994.

5.      Digital Equipment Corporation World Wide Web site, http://www.dec.com.

6.      Digital Equipment Corporation, “Digital DCE for Windows NT helpfiles”, 1996.

7.      Gradient World Wide Web site, http://www.gradient.com.

8.      Richard Grimes, Professional DCOM Programming, Wrox Press Ltd., 1997.

9.      Hewlett Packard World Wide Web site, http://www.hp.com.

10.  P. E. Chung, Y. Huang, S. Yajnik, D. Liand, J. Shih, C. Y. Wang, and Y. M. Wang, “DCOM and CORBA: Side by Side, Step by Step, and Layer by Layer”, Patterns++ Column, C++ Report, SIGS Publications, Inc., January 1998.

11.  IBM World Wide Web software site, http://ww.software.ibm.com.

12.  IBM World Wide Web networking site, http://www.networking.ibm.com.

13.  Infobeads World Wide Web site, http://www.ci.infobeads.com.

14.  Harold W. Lockhart, Jr., OSF DCE Guide to Developing Distributed Applications, McGraw-Hill, Inc., 1994.

15.  Microsoft Corporation, “The Foundations of Microsoft Windows NT System Architecture”, September 1997.

16.  Microsoft Corporation, “Windows NT Resource Kit”, 1997.

17.  Microsoft Corporation, “The Component Object Model Specification”, Draft 0.9, October 24, 1995.  Available on MSDN.

18.  Microsoft Corporation World Wide Web site, http://www.microsoft.com.

19.  Microsoft Corporation, Microsoft Developers Network (MSDN) CD collection, “Platform SDK Documentation – Networking and Distributed Services – RPC – The Microsoft RPC Model”, January 1998.

20.  Microsoft Corporation, Microsoft Developers Network (MSDN) CD collection, January 1998.

21.  Object Management Group World Wide Web site, http://www.omg.org.

22.  Open Group World Wide Web site, http://www.camb.opengroup.org.

23.  Ward Rosenberry, David Kenney, and Gerry Fisher, Understanding DCE, O’Reilly and Associates, Inc., 1992.

24.  Ward Rosenberry and Jim Teague, Distributing Applications Across DCE and Windows NT, O’Reilly and Associates, Inc., 1993.

25.  John Shirley and Ward Rosenberry, Microsoft RPC Programming Guide, O’Reilly and Associates, Inc., 1995.

26.  John Shirley, Wei Hu, and David Magid, Guide to Writing DCE Applications, O’Reilly and Associates, Inc., 1994.

27.  Swapnesh C. Shirolkar, “Intermediary Servers”, Masters Thesis, University of Missouri, 1994.

28.  Vepa V. Sirish, “Application Level Gateways”, Masters Thesis, University of Missouri, 1996.

29.  Michael Stal, Siemens AG, “Distributed Object Computing”, presented at the 1997 OOPSLA conference in Atlanta, GA., sponsored by the Association for Computing Machinery (ACM).

30.  Bjarne Stroustrup, The C++ Programming Language, Third Edition, Addision Wesley Longman, Inc., 1997.

31.  Andrew S. Tanenbaum, Computer Networks, Second Edition, Prentice-Hall, Inc., 1988.


Appendix A: BINOP Source Code

 

The code, including the build environment, for the BINOP project was originally written by Prof. Gordon K. Springer of the University of Missouri-Columbia .  Included here is a modified version of BINOP, used with permission of the author, which can be built and executed on Microsoft platforms.  The files SERVICE.H and SERVICE.C were originally written by Microsoft as samples and are included here in slightly modified form as part of the BINOP project.

Note that there are two build targets: Win32 and Win32RAW.  The Win32RAW target builds the project with only the Microsoft supplied DCE services (i.e., Microsoft RPC).  This target only builds BINOPC, the BINOP worker client program, since BINOPC only requires RPC to function, and the target does not require any special tools, libraries, or headers save the Microsoft-supplied utility header file, DCEPORT.H.  The Win32 target builds the complete BINOP project, but requires the Digital DCE ADK in order to build.  The resultant binaries from the Win32 target require the Digital DCE Runtime in order to execute.

It is helpful to note that several environment variables control the execution of the various BINOP programs.  The variable “PRINCIPAL” controls the principal name that is used by a server (either FINDS or BINOPS) to login to a DCE cell.  Similarly, the variable “PASSWORD_FILE” directs the server programs to the location of a file that contains an (optionally) encrypted password for the principal.  The “MUNS_CONF” variable provides a space-delimited list of FINDS servers that can be used to lookup BINOPS servers.  For the purposes of easy demonstration, each of these variables has a predefined default.  The WIN32 platform defaults follow:  PRINCIPAL defaults to “Springer”.  PASSWORD_FILE defaults to “D:\Thesis\password.fil”.  MUNS_CONF defaults to “D:\Thesis\muns.cfg”.

 


BINOP Subproject

 

FILE:BINOP1.C

/*************************************************************************

 * DCE Program Binop1:  BINOP1.C - Functions in the Binop V2 Interface

 *

 * Author:   G.K. Springer

 * Date:     June 1991

 * Node:     condor.cs.missouri.edu

 * Location: Computer Science Department, University of Missouri-Columbia

 *

 * Purpose:  Demonstrate DCE Application Program

 *

 * Function: Define the addition and subtraction functions in Server.

 *           This code is invoked directly by the Binop Server (BINOPS.C)

 *           and indirectly from the Binop Client (BINOPC.C)

 *

 *   V2 has two functions exported by the server: binop_add & binop_sub

 *

 * Syntax: None - these are the functions the client calls in the server

 *

 * Change Log:

 *  03/26/93 - GKS - Defined Version 1 Exported Functions

 *  09/15/93 - GKS - Redefined coding for use in DCE

 *

 *************************************************************************/

 

#include "binop1.h"  /* NIDL generated Interface Definition */

 

 

/*************************************************************************

 * Remote ADD function in the Binop Server Interface

 *************************************************************************/

void binop_add

#ifdef IDL_PROTOTYPES

(

  /*  [in]  */ handle_t     h,

  /*  [in]  */ idl_long_int a,

  /*  [in]  */ idl_long_int b,

  /*  [out] */ idl_long_int *c

)

#else

(h, a, b, c)

  /*  [in]  */ handle_t     h;

  /*  [in]  */ idl_long_int a;

  /*  [in]  */ idl_long_int b;

  /*  [out] */ idl_long_int *c;

#endif

{

  *c = a + b;     /* Compute result and return to caller */

}  /* end binop_add() */

 

/*************************************************************************

 * Remote SUBTRACTION function in the Binop Server Interface

 *************************************************************************/

void binop_sub

#ifdef IDL_PROTOTYPES

(

  /*  [in]  */ handle_t     h,

  /*  [in]  */ idl_long_int a,

  /*  [in]  */ idl_long_int b,

  /*  [out] */ idl_long_int *c

)

#else

(h, a, b, c)

  /*  [in]  */ handle_t     h;

  /*  [in]  */ idl_long_int a;

  /*  [in]  */ idl_long_int b;

  /*  [out] */ idl_long_int *c;

#endif

{

  *c = a - b;      /* compute result and return to caller */

}  /* end binop_sub() */

 

 


FILE:BINOP1.IDL

/*

 *   IDL definition of special binary operations server (BINOP)

 *

 *   Exports Functions: binop$add and binop$sub

 *   Uses: IP Communication to a system allocated port

 *

 *  By: G.K. Springer - July 1991

 *  Modified: GKS - March 1993

 *            GKS - redone for DCE implementation

 */

 

[

uuid(249dacc0-ac8d-11cc-89ce-08002b37598d),

version(1.0)

]

 

 

interface binop

{

/* Define Addition Exported Function */

[idempotent]

void binop_add(

    [in]  handle_t  h,    /* Communication Handle */

    [in]  long  a,        /* Parameter 1 for add */

    [in]  long  b,        /* Parameter 2 for add */

    [out] long  *c        /* Result of add to return */

    );

 

/* Define Subtraction Exported Function */

[idempotent]

void binop_sub(

    [in]  handle_t  h,    /* Communication Handle */

    [in]  long  a,        /* Parameter 1 for subtract */

    [in]  long  b,        /* Parameter 2 for subtract */

    [out] long  *c        /* Result of subtract to return */

    );

}

 

 


FILE:BINOPC.C

/*************************************************************************

 * DCE Program Binopc:  BINOPC.C - Client Application Program

 *

 * Author:   G.K. Springer

 * Date:     October 1993

 * Node:     condor.cs.missouri.edu

 * Location: Computer Science Department, University of Missouri-Columbia

 *

 * Purpose:  Demonstrate DCE Application Program

 *

 * Function: Implement an addition and subtraction RPC service.

 *

 * Syntax:   This program is invoked with the command line:

 *               BINOPC <server_host> <num_passes>

 *           where:

 *            server_host - identifies the host where server is running

 *            num_passes  - indicates how many loops of requests to perform

 *

 * Example:  binopc cyclone.cs.missouri.edu 3

 *************************************************************************/

/*

 * Standard C Include files

 */

#include <stdio.h>

#ifndef WIN32

#include <unistd.h>

#endif

#ifndef WIN32RAW

#include <pthread.h>

#endif

 

/* Include NCS Definitions */

#ifdef WIN32RAW

#include <rpc.h>

#include "dceport.h"

#else

#include <dce/rpc.h>  /* DCE RPC definitions */

#endif

#include "binop1.h"   /* NIDL generated Interface definitions */

#include "binopnms.h" /* Binop Name Strings */

 

 

/***************************************************************************

 * BINOPC -  Client Main Program

 ***************************************************************************/

main(int   argc, char  **argv)

{

  int                  passes;  /* Input parameter for passes to run */

  int                  i;       /* temp loop counter */

  int                  result;  /* temp result */

  rpc_if_id_t          ifid;  /* interface identifier */

  unsigned32           st;  /* Return status from RPC calls */

  rpc_binding_handle_t rh;  /* RPC handle for communication */

  unsigned_char_t      *string_binding;  /* String binding handle */

  rpc_protseq_vector_t *protvec;   /* protocol sequence vector */

  char                 host[NMLEN];  /* hostname for server */

 

/***************************************************************************

 * Start of main() program

 ***************************************************************************/

   if (argc < 3) {

       fprintf(stdout,"usage: %s hostname passes\n", *argv);

       exit(1);

       }

 

   strcpy(host, argv[1]); /* move Server hostname */

   passes = atoi(argv[2]); /* get number of passes to run */

 

/* Find supported protocols on this system */

   rpc_network_inq_protseqs( &protvec, &st);  /* get protocol strings */

   if (st != rpc_s_ok) {

      fprintf(stdout, "%s: Cannot obtain supported protocols\n", *argv);

      exit(1);

      }

 

   fprintf(stdout, "This system supports %d protocols\n", protvec->count);

   for (i=0; i<protvec->count; i++) {

      fprintf(stdout, "Protocol %d: %s\n", i, protvec->protseq[i]);

      }

   fflush(stdout);

 

/*************************************************************************

 * Loop thru protocols to find a binding handle that is active on host

 *************************************************************************/

   for (i=0; i<protvec->count; i++) {

 

   /* Compose the string first so handle can be obtained from it */

      rpc_string_binding_compose((unsigned_char_t *)OBJSTR,

         protvec->protseq[i], (unsigned_char_t *)host,

         NULL, NULL, &string_binding, &st);

      if (st != rpc_s_ok) {

          fprintf(stdout,"Cannot compose string binding\n");

          result = -1;

          }

 

      /* Get the partially bound handle from the constructed string */

      rpc_binding_from_string_binding (string_binding, &rh, &st);

      if (st != rpc_s_ok) {

        printf("Cannot convert name %s to binding\n",string_binding);

        result = -1;

        }

      else result = 0;

 

      /* Free the string info we don't need any more */

      rpc_string_free(&string_binding, &st);

      /* Set timeout commensurate with the protocol */

      rpc_mgmt_set_com_timeout(rh, i+1, &st);

      rpc_ep_resolve_binding(rh, C_IFSPEC, &st);

      if (st != rpc_s_ok) result=-1;

      if (result==0) break;

      }  /* end of for loop to build a handle */

 

/* We have a handle or we don't - so free protocol vector */

   rpc_protseq_vector_free(&protvec, &st);

   if (result != 0) {

      printf("Unable to connect to server on %s\n", host);

      exit(1);

      }

  

/***********************************************************************

 * All set - make appropriate number of passes to Server RPC Functions

 ***********************************************************************/

   makepass(rh, passes);  /* All work is done in this routine */

   exit(0);  /* We are done - Let's go home */

}  /* End BINOPC main() */

 


FILE:BINOPDEM.C

/****************************************************************************

 * DCE Demo Program:  BINOPDEMO.C - Client Application

 *

 * Author:   G.K. Springer

 * Date:     February 1992

 * Node:     condor.cs.missouri.edu

 * Location: Computer Science Department - MU, Columbia, MO.

 *

 * Purpose:  Demonstrate DCE Application Program

 *

 * Function: Implement an addition and subtraction RPC service.

 *

 * Syntax:   This program is invoked with the command line:

 *              BINOPDEMO

 *

 * Change Log:

 * 09/93 - GKS - Rewrite code for DCE Nameservice Lookup

 *

 ****************************************************************************/

 

/*

 * Standard C Include files

 */

#include <stdio.h>

#ifndef WIN32

#include <unistd.h>

#endif

#include <stdlib.h>

#include <signal.h>

#include <sys/types.h>

#include <time.h>

#include <pthread.h>

 

/*

 * Include DCE Definitions

 */

#include <dce/rpc.h>  /* DCE RPC definitions */

#include <dce/dce_error.h>  /* DCE error definitions */

#include "binop1.h"  /* NIDL generated Interface definitions */

#include "binopnms.h"  /* Binop Name Definitions */

char     *mc = {"bcdefghijk"};

 

#ifdef WIN32

#define  CLEARIT  "cls"

#else

#define  CLEARIT  "clear"

#endif

 

#define  HELPER   "binophlp | more"

#define  STATS    "binopst | more"

#define  MaxSrv   20

 

 

/***********************************************************************

 * BINOPDEMO -  Demo Main Program

 ***********************************************************************/

main(int argc, char **argv)

{

   int            passes;   /* Input parameter for passes to run */

   int            num_entry;  /* Number of server registrations */

   int            nsrv;  /* number of servers in demo run */

   int            i, j, l;   /* Temp variables */

   int            index[MaxSrv+1];  /* Index to servers */

   int            proto[MaxSrv+1]; /* Index to handles we use */

   rpc_binding_vector_t   *results;   /* NS lookup results */

   unsigned32     st;  /* Return status from RPC calls */

   char           group_name[NMLEN];  /* name of group to search NS */

   char           ch; /* read character input */

   char           maxsrv; /* max servers in run */

   char           string[256], *sp;

   unsigned_char_t *string_binding;

 

/***************************************************************************

 * Start of main() program

 ***************************************************************************/

   printf("Please wait a minute while we get setup ...\n");

/*

 *  Lookup the BINOP Object Uuid in the DCE NameService Database

 */

   strcpy(group_name, GRPNAME);  /* identify the group desired */

   num_entry = findsrvs(group_name, OBJSTR, binop_v1_0_c_ifspec, &results,

                   MaxSrv, &st);  /* lookup servers */

   if (num_entry == 0)  {  /* No servers found registered */

      printf("Lookup for BINOP Servers Failed - %s\n", dcemsg(st));

      }

 

/*

 * Sort out the unique servers in the list of handles

 */

   j = s_handle(num_entry, &nsrv, results, index, proto);

 

 /*

 *  For each server found running, complete the binding information

 */

   for (i=0; i<nsrv; i++)  {

      rpc_mgmt_set_com_timeout(results->binding_h[proto[i]],

          rpc_c_binding_min_timeout, &st); /* timeout quickly */

      rpc_ep_resolve_binding(results->binding_h[proto[i]],

                             binop_v1_0_c_ifspec, &st);

      }  /* End for each server loop */

  

   maxsrv = 'a' + nsrv;

   passes = 1; /* get number of passes to run */

 

 

/************************************************************************

 *  Loop on the menu until request to quit

 ************************************************************************/

  for (;;) {

     system(CLEARIT);

     printf("\t\tDCE Remote Procedure Call Demonstration\n");

     printf("\t\t---------------------------------------\n\n");

     printf("a:  Issue RPC requests to ALL Systems\n");

     for (i=0; i < nsrv; i++) { /* Output the menu for servers */

        printf("%1c:  Issue RPC requests to ", mc[i]);

        p_handle(results->binding_h[proto[i]]); /* print who we talk to */

        }

     if(nsrv > 0) printf("\n");

     printf("r:  Refind the running servers\n");

     printf("s:  Print statistics from servers\n");

     printf("u:  Print a description of the RPC Demo\n\n");

     printf("q:  Terminate the Demo\n\n");

     printf("Please enter the character for the menu item desired\n");

 

     sp =gets(string);

     if (sp == NULL) break;

     l = sscanf(string,"%c",&ch);

     if (l == 1) {

        if (((ch<'a') | (ch > maxsrv)) &

             (ch!='u') & (ch!='q') & (ch!='r') & (ch!='s') ) ch='z';

     else {

        i = ch - 'b';  /* get index of hostname desired */

        if ((ch>'a') & (ch<'k')) ch='b'; /* access 1 server */

        }

 

        switch (ch) {

        case 'a': system(CLEARIT);

                  for (i=0; i<nsrv; i++) {  /* Call all servers */

                     makepass(results->binding_h[proto[i]], passes);

                     }

                  break;

        case 'b': system(CLEARIT);

                  makepass(results->binding_h[proto[i]], passes);

                  break;

        case 'r': rpc_binding_vector_free(&results, &st);  /* free vector */

                  num_entry = findsrvs(group_name, OBJSTR, binop_v1_0_c_ifspec,

                                  &results, MaxSrv, &st);  /* lookup servers */

                  j = s_handle(num_entry, &nsrv, results, index, proto);

                  maxsrv = 'a' + nsrv;  /* identify last server index */

                  for (i=0; i<nsrv; i++)  {

                     rpc_ep_resolve_binding(results->binding_h[proto[i]],

                         binop_v1_0_c_ifspec, &st);

                     }  /* End for each server loop */

                  break;  /* done - just go back and redisplay menu */

        case 's': system(CLEARIT);  /* show stats on servers */

                  system(STATS);  /* give them stats from the servers */

                  break;

        case 'u': system(CLEARIT);

                  system(HELPER);  /* give them help info on demo */

                  break;

        case 'q': printf("\n***End of RPC Demo***\n");

                  rpc_binding_vector_free(&results, &st);  /* free vector */

                  exit(0); /* We are done - Let's go home */

        default:  printf("Invalid option selected - try again.\n");

                  break;

        }  /* end switch */

     }  /* end if */

  printf("\nHit ENTER key to make next selection\n");

  sp =gets(string);

  if (sp == NULL) break;

  }  /* end for */

  rpc_binding_vector_free(&results, &st);  /* free binding vector */

  exit(0);

 

}  /* End BINOPDEMO main() */

 

 


FILE:BINOPHLP.C

/****************************************************************************

 *  BINOPHLP.C - Print HELP information about the BINOPDEMO demonstration.

 *

 * Author:   G.K. Springer

 * Date:     March 1993

 * Node:     cyclone.cs.missouri.edu

 * Location: Computer Science Department - MU, Columbia, MO.

 *

 * Purpose:  Tell user about the BINOPDEMO demonstration program.

 * Function: This program simply prints lines to stdout that explains the

 *           demonstration program.  This program is invoked from the demo

 *           menu (option 'h').  During its execution, this program searches

 *           for the BINOP servers registered in the network.  For each

 *           server found, bind to the server and print out the information

 *           found in the Location Broker database about the server.  This

 *           information may or may not exactly agree with the servers listed

 *           on the menu and an entirely new lookup is performed here.  If

 *           there is a disagreement with the menu, requesting the demo to

 *           relookup the servers should put this HELP and the menu back in

 *           synchronization.

 *

 * Change Log:

 *  09/93 - GKS - Revised for use in DCE environment

 ****************************************************************************/

 

/*

 * Standard C Include files

 */

#include <pthread.h>

#ifndef WIN32

#include <unistd.h>

#endif

#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

#include <sys/types.h>

 

/*

 * DCE Definitions

 */

#include <dce/rpc.h>

#include <dce/rpcexc.h>

#include <dce/uuid.h>

 

/* Include DCE Application Definitions */

#include "binop1.h"   /* IDL generated Interface definition */

#include "binopnms.h"  /* Binop Name Strings */

 

extern char *error_text();

#define MaxSrv  6

 

 

/************************************************************************

 * BINOPHLP -  Server Status Main Program

 ***********************************************************************/

main(int argc, char **argv)

{

  int            i,j;         /* Counters - temp */

  unsigned32     st;          /* Status of calls made */

  unsigned32     max_entry;   /* NS lookup max entries */

  unsigned32     num_entry;   /* NS lookup num entries returned */

  rpc_binding_vector_t  *results;  /* NS lookup results */

  char           group_name[NMLEN];  /* name of group to search NS */

 

/************************************************************************

 *   Start of main program

 ***********************************************************************/

 

/* Print help info about the binopdemo program */

 

printf("              DCE Remote Procedure Call Demonstration\n");

printf("              ---------------------------------------\n");

printf("\n");

printf("\n");

printf("This demonstration shows the operation of using remote  procedure\n");

printf("calls from one workstation to another workstation that is running\n");

printf("a server. In this demonstration, some number of servers have been\n");

printf("started on separate machines in the network.  The exact number is\n");

printf("not known until this program  searches the network  to find where\n");

printf("the servers are located.   The servers found to be running in the\n");

printf("network will be listed on the main menu of this demonstration. If\n");

printf("no servers  are found to be running, no servers will be listed on\n");

printf("the menu.  The search for the location of running servers is done\n");

printf("by using  Distributed Computing Environment (DCE) Name Service to\n");

printf("find the servers that have \"registered\" themselves in the network.\n");

printf("\n");

printf("Each time  this demonstration program is run,  a different set of\n");

printf("servers  may be listed on  the menu.   Depending upon  where each\n");

printf("server has been started,  this demonstration  program will locate\n");

printf("them dynamically and list  only those servers  that are currently\n");

printf("active in the network.  By looking at the server locations listed\n");

printf("on the main menu,  you can see where they are located and be able\n");

printf("to request services from them individually or as a group.   As an\n");

printf("example, the current list of registered servers is:\n");

printf("\n");

 

/*

 *  Lookup the BINOP Object Uuid in the NameService Database

 */

   strcpy(group_name, GRPNAME);  /* identify the group desired */

   num_entry = findsrvs(group_name, OBJSTR, binop_v1_0_c_ifspec, &results,

                        MaxSrv, &st);  /* lookup servers */

  if (num_entry == 0)  {  /* No servers found registered */

     printf("\n\t*** No Binop Servers are currently registered ***\n");

     }

  else {

    /*

     *  For each server found running, Print out where it is located.

     */

     printf("\n");

     for (j=0; j<num_entry; j++)  {

        rpc_mgmt_set_com_timeout(results->binding_h[j],

            rpc_c_binding_min_timeout, &st); /* timeout quickly */

        printf("\tServer %c:  ", 'b'+j);

        p_handle(results->binding_h[j]); /* print who we talk to */

        }  /* end for */

     rpc_binding_vector_free(&results, &st);  /* free binding vector */

     }  /* end else */

 

printf("\n");

printf("\n");

printf("Each of the servers offer two services; an addition service and a\n");

printf("subtraction  service.   Each  request  to  a  server  passes  two\n");

printf("parameters, A and B, which are to be operated upon by the server.\n");

printf("The  addition  service  ADDS  the  two parameters and returns the\n");

printf("result C to the caller.  The subtraction  service  SUBTRACTS  the\n");

printf("two parameters and returns the result C to the caller.\n");

printf("\n");

printf("In this demo, a loop that performs 50 requests to the add service\n");

printf("and  50  requests  to  the  subtract  service  are  made  to  the\n");

printf("designated server.  As the result from each request  is  returned\n");

printf("to the caller (this demo program), it is displayed on the screen.\n");

printf("This lets you see how quickly each of the requests are  serviced.\n");

printf("Timing  is  done  across  all of the requests and a final line is\n");

printf("written  to  the  screen  that  shows  the  average   number   of\n");

printf("milliseconds each particular request took to complete.\n");

printf("\n");

printf("The requests to the servers are all of the form:\n");

printf("\n");

printf("       c = i + i    (for Addition Service)\n");

printf("\n");

printf("       c = 51 - i   (for Subtraction Service)\n");

printf("\n");

printf("   where: i is the index of loop sending requests to the server.\n");

printf("          c is the result computed by the server and returned to\n");

printf("            the caller.\n");

printf("\n");

printf("\n");

printf("Although this is a very simple demonstration, it shows the  power\n");

printf("of  being  able  to  utilize  the  computational power of another\n");

printf("machine to  perform  the  operations  needed  by  an  application\n");

printf("program.    There   is  no  limit  to  the  type  and  volume  of\n");

printf("computations that could be performed by the server.  If you think\n");

printf("about  it,  the server could be a very large machine (like a CRAY\n");

printf("supercomputer) which could perform the  needed  computations  far\n");

printf("faster  than the local application program could perform them for\n");

printf("itself.\n");

printf("\n");

printf("Since the calls to the server are made in the  same  way  as  you\n");

printf("would  make  them to a procedure or function in your own program,\n");

printf("the amount of time needed to build such distributed  applications\n");

printf("is actually very small.  As a case in point, the actual code used\n");

printf("to make the server requests in this demo are shown below.\n");

printf("\n");

printf("To run this demo, simply select one of the options  displayed  on\n");

printf("the menu screen and sit back and watch what happens.\n");

printf("\n");

printf("Hope you enjoy the demonstration!!\n");

printf("\n");

printf("\n");

printf("\n");

printf("\n");

printf("  Source Code used in DEMO to make Server Requests\n");

printf("  ------------------------------------------------\n");

printf("\n");

printf("\n");

printf("/*****************************************************************\n");

printf(" * makepass() - run the demo on one of the requested servers      \n");

printf(" *****************************************************************/\n");

printf("makepass(handle_t rh, int passes) \n");

printf("{\n");

printf("   int       k;      /* Temp counter for passes run */\n");

printf("   int       i, n;   /* Temp variables */\n");

printf("   status_t  st;     /* Return status from RPC calls */\n");

printf("   int start_time, stop_time; /* Timing variables */\n");

printf(" \n");

printf("   printf(\"\\nStart Requests to Server: \\n\");\n");

printf("   p_handle(rh);\n");

printf("\n");

printf("/*********************************************************************\n");

printf(" * Loop for the requested number of passes to Server RPC Functions\n");

printf(" *********************************************************************/\n");

printf("   for (k = 1; k <= passes; k++) {\n");

printf("      start_time = time(NULL);  /* Get TOD at start of a pass */\n");

printf(" \n");

printf("     /*\n");

printf("      * Call addition service the required number of times\n");

printf("      */\n");

printf("      for (i = 1; i <= CALLS_PER_PASS; i++) {\n");

printf("         binop_add(rh, i, i, &n);  /* Call RPC ADD service on Server */\n");

printf("         printf(\"%%3d \",n); /* Print result returned */\n");

printf("         /* add a newline every 10 results returned */\n");

printf("         if ((i%%10 == 0) && (i != CALLS_PER_PASS)) printf(\"\\n\");\n");

printf("         }  /* end for i - addition loop */\n");

printf("      printf(\"  *** end of addition ***\\n\");\n");

printf(" \n");

printf("     /*\n");

printf("      * Call subtraction service the required number of times\n");

printf("      */\n");

printf("      for (i = 1; i <= CALLS_PER_PASS; i++) {\n");

printf("         binop_sub(rh, CALLS_PER_PASS+1 , i, &n); /* Call RPC SUB service */\n");

printf("         printf(\"%%3d \",n);  /* Print result returned */\n");

printf("         /* add a newline every 10 results returned */\n");

printf("         if ((i%%10 == 0) && (i != CALLS_PER_PASS)) printf(\"\\n\");\n");

printf("         }  /* end for i - subtraction loop */\n");

printf("      printf(\"  *** end of subtraction ***\\n\");\n");

printf(" \n");

printf("     /*\n");

printf("      * Calculate average time to process a call\n");

printf("      */\n");

printf("      stop_time = time(NULL);  /* Get TOD at end of pass */\n");

printf("      printf(\"***** pass %%3d; real/call: %%2d ms\\n\",\n");

printf("         k, ((stop_time - start_time) * 1000) / (2*CALLS_PER_PASS));\n");

printf("      }  /* end for k - number of passes */\n");

printf("}  /* end makepass() */\n");

printf("\n");

 

exit(0);

}  /* end binophlp() */

 

 


FILE:BINOPMSG.C

/****************************************************************************

 * BINOPSMSG.C - Get DCE Error Messages from error message table.

 *

 * Author:   G.K. Springer

 * Date:     March 1993

 * Node:     cyclone.cs.missouri.edu

 * Location: Computer Science Department - MU, Columbia, MO.

 *

 * Purpose:  Utility to get an NCS run-time error message from the message

 *           table and return the message string to the caller.

 * Function: Access external message table by error number and return string

 *           to the caller.

 *

 * Change Log:

 *  09/93 - GKS - Changed for DCE implementation

 *

 * Note:

 *  To get error messages an environment variable NLSPATH is required.

 *  Define it as:  setenv NLSPATH "/opt/dcelocal/nls/msg/en_US.88591/%N"

 *

 ****************************************************************************/

 

/* Include DCE Definitions */

#include <dce/rpc.h>

#include <dce/dce_error.h>

 

char *error_text(int st)

{

  int         err_st;   /*CRAY*/

  static char buff[dce_c_error_string_len];

 

  dce_error_inq_text(st, buff, &err_st);

  if (err_st != -1) return(buff);

  else  {

     if (st == 0xc038a0e0) 

        sprintf(buff, "DCE/RT - Server not responding");

     else

        sprintf(buff, "DCE/RT - No error text translation, st=%08x",st);

     return(buff);

     }

     

}  /* binopsmsg() */

 

 


FILE:BINOPNMS.H

/*************************************************************************

 * DCE Program Binop:  BINOPNMS.H - Include File.

 *

 * Author:   G.K. Springer

 * Date:     September 1993

 * Node:     condor.cs.missouri.edu

 *

 * Purpose:  Include file for BINOP application programs

 *

 * Function: Define the OBJ UUID string, Group Name, Entry Name

 *           and Annotation Names for the Binop Application code.

 *

 * Syntax:   Include file for C syntax programs

 *

 * Update Log:

 * 09/93 - GKS - Rewrite of code for DCE environment

 *************************************************************************/

 

#define  GRPNAME  "/.:/hpcc/Binop_Group"

#define  ENTNAME  "/.:/hpcc/Binop_"

//#define  GRPNAME  "/.:/hpcc/test/Binop_Group"

//#define  ENTNAME  "/.:/hpcc/test/Binop_"

#define  EPNAME   "BINOP Server V2"

#define  NMLEN    50

 

#define  S_IFSPEC  binop_v1_0_s_ifspec

#define  C_IFSPEC  binop_v1_0_c_ifspec

#define  OBJSTR   "aaaa4000-b04b-11cc-bf88-08002b37598d"

 

 


FILE:BINOPS.C

/*************************************************************************

 * DCE Program Binops:  BINOPS.C - Server Routine.

 *

 * Author:   G.K. Springer

 * Date:     June 1991

 * Node:     condor.cs.missouri.edu

 * Place:    Computer Science Department, University of Missouri-Columbia

 *

 * Purpose:  Demonstrate DCE Application Program

 *

 * Function: Implement an addition and subtraction RPC service.

 *

 * Syntax: This program is invoked with the command line:

 *            BINOPS  [&]     (should invoke program in background)

 *

 * Change Log:

 *  10/93 - GKS - Rework code to run in DCE environment using DCE Name

 *                Service across multiple DCE Cells.

 * Note:

 *    February 1994 - GKS - Added processing code

 *    A dedicated signal catching thread is used to allow the server to

 *    terminate gracefully in the presence of a fatal asynchronous signal.

 *    This thread is created by the server and gains control in sigcatch()

 *    whenever a non-DCE termination signal is received by the server.

 *

 *    A dedicated self-authentication thread is used to keep the server's

 *    credentials current.  It wakes up just prior to the credentials

 *    expiring and reauthenticates itself to DCE so it always remains

 *    authenticated - regardless of what its expiration limit is and how

 *    long it has been running.  One requirement is the principle must be

 *    able to refresh its certificates and the ticket lifetime must be

 *    greater than 10 minutes.

 *************************************************************************/

 

/*

 * Standard C Include files

 */

#include <stdio.h>

 

#ifndef WIN32

#include <unistd.h>

#include <sys/errno.h>

#else

#include <errno.h>

#endif

 

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <pthread.h>

 

/* Include DCE Definitions */

#include <dce/rpc.h>  /* DCE RPC definitions */

 

char            *pnm;                   /* program name pointer for msgs */

char            msg[144];               /* For time-stamped messages */

#ifndef WIN32

pid_t           pid;                    /* Process id of the server */

#else

int           pid;                    /* Process id of the server */

#endif

uuid_t          objuuid;                /* binary object uuid string */

rpc_if_id_t     ifid;                   /* interface identifier */

uuid_vector_t   *obj_uuid_vector;       /* object uuid vector for register */

rpc_binding_vector_t  *binding_vector;  /* Bindings for server */

int             logflg;

 

/* Define Server Specific Functions and Names */

#include <musrv.h>

 

 

/***************************************************************************/

/***************************************************************************/

/* This conditional code has been added to allow WIN32 servers to start as */

/* services.  The utility code contained in service.h and service.c is     */

/* taken from a Microsoft sample program called "Simple Service".  It is   */

/* included with minor modifications.                                      */

/* JimR 3/1/97                                                             */

/***************************************************************************/

#ifdef WIN32

#ifndef NODAEMON

 

#include <service.h>

 

#define SZAPPNAME                               "BinopS"

#define SZSERVICENAME                    "BinopS"

#define SZSERVICEDISPLAYNAME      "DCE BINOP Server"

#define SZDEPENDENCIES                   ""

 

#include <service.c>

 

VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)

{

       /**********************************************/

       /* PROBLEM! - We really shouldn't tell control*/

       /* panel that we are up and running until we  */

       /* have registered the endpoints and all.     */

       /* However, this way allows WIN32 to act more */

       /* nearly like the other environments.        */

       /**********************************************/

 

       /* Let control panel know that we are running */

       ReportStatusToSCMgr(SERVICE_RUNNING,NO_ERROR,0);

 

       /* Start doing our work as usual */

       main_worker(lpszArgv);

}

 

VOID ServiceStop()

{

       /* Warn the SCMgr that we may take up to 10 secs to stop */

       ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,10000);

 

       /* Fake a CTRL-C to shutdown service */

       SignalHandlerRoutine(CTRL_C_EVENT);

}

 

#else         /* NODAEMON */

main(int argc, char **argv)

{

       main_worker(argv);

}

#endif /* NODAEMON */

 

#else         /* WIN32 */

main(int argc, char **argv)

{

       main_worker(argv);

}

#endif /* WIN32 */

/***************************************************************************/

/***************************************************************************/

 

 

 

/***************************************************************************

 * Server Main Program

 ***************************************************************************/

main_worker(char **argv)

{

  double         dum1;  /* Force vars to align on a double boundary */

  int            i;     /* loop index */

  char           logname[128];  /* name of the log file */

  FILE           *fp;   /* temp file pointer to log file */

  unsigned32     st;    /* DCE status return codes on calls */

  unsigned32     thread_stk_size;  /* stack size for threads */

  int            thread_status;

  pthread_t      refresh_thread;   /* refresh thread to keep server

                                    * sec_credentials active */

  pthread_t      sigcatch_thread;  /* signal catching thread for

                                    * graceful shutdowns */

  pthread_attr_t attr;  /* attributes of a thread */

 

/************************************************************************

 *   Start of main program

 ************************************************************************/

 

/* get short name of program */

#ifdef WIN32

/* JimR Note - Changed from rindex to strrchr since only the latter */

/* is supported on MS platforms and is also supported on all UNIX   */

#define rindex strrchr

/* JimR Note - looking for slash on Unix, or backslash on MS platforms */

#define PathDelimiter      '\\'

#else

#define PathDelimiter      '/'

#endif

  pnm = rindex(*argv, PathDelimiter);

  if (pnm == NULL) pnm = *argv;

  else pnm = pnm+1;

 

#ifndef WIN32

  umask(027);  /* make desired file mode creation mask */

#endif

  regstat = 0;  /* init registration status */

 

#ifndef NODAEMON

/************************************************************************

 * Compile this code if we are creating a Daemon Server

 ************************************************************************/

 

/* create name of log file and test its use for stdout and stderr */

  sprintf(logname, "%s/%s.log", LOGDIR, pnm);

  if ((fp = fopen(logname, "a")) == NULL) {

     sprintf(msg, "%s: could not open log:\n\t%s", pnm, logname);

     tmsg(msg);

     exit(1);

     }

 

/* make ourselves into a daemon */

  i = daemon_init();

  if (i < 0) {

     sprintf(msg, "%s: error forking child process\n", pnm);

     tmsg(msg);

     fclose(fp);

     exit(1);

     }

 

/* we are now a daemon - so redirect stdout and stderr to log file */

  if (freopen(logname, "a", stdout) == NULL) {

     fprintf(fp, "%s: could not reopen stdout to log:\n\t%s", pnm, logname);

     exit(1);

     }

  if (freopen(logname, "a", stderr) == NULL) {

     fprintf(fp, "%s: could not reopen stderr to log:\n\t%s", pnm, logname);

     exit(1);

     }

  fclose(fp);   /* and close the temp file pointer */

#endif

 

  printf("\n************************************************************\n");

  sprintf(msg, "%s: Server starting execution...", pnm);

  tmsg(msg);

  logflg= 1;

 

#include <srvbase.h>  /* bring in code for the base server */

 

} /* end main */

 

#include <srvcln.h>  /* bring in code for the base cleanup routines */

 

 


FILE:BINOPST.C

/****************************************************************************

 * BINOPST.C - Print Statistics about BINOP servers running on network.

 *

 * Author:   G.K. Springer

 * Date:     November 1991

 * Node:     cyclone.cs.missouri.edu

 * Location: Computer Science Department - MU, Columbia, MO.

 *

 * Purpose:  Use rpc call to get server stats from BINOP servers running.

 * Function: Lookup the BINOP servers registered in the network.  For each

 *           server found, bind to the server and issue an inquire stats

 *           request and print out the returned statistics.  If the server

 *           does not respond (using short timeout periods), print an

 *           error message so indicating.  This code uses the pthread

 *           error handling facilities built into DCE RunTime code.

 *

 * Change Log:

 * 09/93 - GKS - Rewrite code for DCE Nameservice Lookup

 *

 ****************************************************************************/

 

/*

 * Standard C Include files

 */

#include <stdio.h>

#ifndef WIN32

#include <unistd.h>

#include <sys/errno.h>

#else

#include <errno.h>

#endif

#include <stdlib.h>

#include <sys/types.h>

 

/* Include DCE Definitions */

#include <pthread.h>

#include <dce/rpc.h>  /* DCE RPC definitions */

#include <dce/rpcexc.h>

 

/* Include DCE Application Definitions */

#include "binop1.h"   /* IDL generated Interface definition */

#include "binopnms.h"

 

#define MaxSrv  6

 

char *dcemsg();

unsigned32 p_handle();

 

static char *stname[] = { "   Calls In:   ",

                          "   Calls Out:  ",

                          "   Packets In: ",

                          "   Packets Out:" };

 

/************************************************************************

 *  Server Status Main Program

 ***********************************************************************/

 

main(int argc, char **argv)

{

   int                i,j;           /* Counters - temp */

   int                max_entry;     /* LB lookup max entries */

   int                num_entry;     /* LB lookup num entries returned */

   unsigned32         st;            /* Status of calls made */

   rpc_stats_vector_t *stats;        /* Array of stat values returned */

   rpc_binding_vector_t *results;    /* LB lookup results */

   char               group_name[NMLEN];  /* name of group to search NS */

 

 

/************************************************************************

 *   Start of main program

 ***********************************************************************/

   printf("\n************ Start Stats from BINOPS Servers ************\n");

   system("echo %_date% %_time%");  /* timestamp the output */

 

/*

 *  Lookup the Object Uuid in the NameService Database

 */

   if (argc == 1) {

      strcpy(group_name, GRPNAME);  /* identify the group desired */

      }

   else {

      strcpy(group_name, *(argv+1));  /* user specified the name */

      }

 

   max_entry = MaxSrv;

 

       #ifdef DEBUG

       printf("Looking up group name: %s.\n",group_name);

       #endif

 

   num_entry = findsrvs(group_name, OBJSTR, C_IFSPEC,

                        &results, max_entry, &st);  /* lookup servers */

   printf("Lookup  status: %08x  num_entry= %d\n", st, num_entry);

 

   if (num_entry == 0)  {  /* No servers found registered */

      printf("Lookup for BINOPS Servers Failed - %s\n", dcemsg(st));

      exit(1);

      }

 

/*

 *   Found at least 1 server - allocate a RPC handle to use

 */

   printf("--------------------------------------------------------\n");

 

/*

 *  For each server found running, inquire about its status

 */

for (j=0; j<num_entry; j++)  {

   rpc_mgmt_set_com_timeout(results->binding_h[j],

       rpc_c_binding_min_timeout, &st); /* timeout quickly */

   printf("   Server: ");

   if (p_handle(results->binding_h[j]) == 1) {  /* print who we talk to */

      printf("\tserver registered, but not communicating\n");

      printf("--------------------------------------------------------\n");

      }

   else {

    TRY {

 

              /*******************************************************/

              /* Notes on why this WIN32 specific hack is necessary  */

              /* - Jim Ries 10/15/95                                 */

              /*                                                     */

              /* Under NT, it seems that the binding handle returned */

              /* by findsrvs() in result has the uuid of OBJSTR.     */

              /* At least under NT, this is correct for making       */

              /* actual calls that do work, e.g, things that binopc  */

              /* would like to do.  However, in order to talk to the */

              /* management entry point vector (EPV), one needs the  */

              /* type uuid assigned to the server via the            */

              /* rpc_object_set_type() call.  Therefore, we must     */

              /* inquire what that id is (using S_IFSPEC for which   */

              /* we must link in the idl-generated server module)    */

              /* and change the object uuid of the binding handle.   */

              /*******************************************************/

              #ifdef WIN32

              {

                     uuid_t                     tuuid;

                     rpc_if_id_t                ifid;                   /* interface identifier */

 

                     #ifdef DEBUG

                     unsigned_char_t *    tmp;

 

                     rpc_binding_inq_object(results->binding_h[j],&tuuid,&st);

                     uuid_to_string(&tuuid,&tmp,&st);

                     printf("The object uuid of the binding handle is: %s\n",tmp);

                     #endif

 

                     rpc_if_inq_id(S_IFSPEC, &ifid, &st);

 

                     #ifdef DEBUG

                     uuid_to_string(&ifid.uuid,&tmp,&st);

                     printf("Changing the binding handle uuid to: %s\n",tmp);

                     #endif

 

                     rpc_binding_set_object(results->binding_h[j],&ifid.uuid,&st);

              }

              #endif

 

     /* Get server statistics and print them out */

     rpc_mgmt_inq_stats(results->binding_h[j], &stats, &st);

     if (st == rpc_s_ok) {

        for (i=0; i<stats->count; i++) printf("%s %d\n", stname[i],

             stats->stats[i]);

        printf("--------------------------------------------------------\n");

        rpc_mgmt_stats_vector_free(&stats, &st);  /* free stats vector */

        }

     else {

        printf("   ***Error*** - Could not obtain stats from server\n");

        printf("--------------------------------------------------------\n");

        }

     }

/*

 *   Comes here on a communication error.

 */

CATCH (rpc_x_comm_failure) {

      printf("   ***Error*** - Server not responding!\n");

      printf("--------------------------------------------------------\n");

      }

/*

 *   Comes here on all other errors.

 */

CATCH_ALL {

      printf("   ***Error*** - %s\n", dcemsg(st));

      printf("--------------------------------------------------------\n");

      }

ENDTRY;

   }  /* if p_handle() */

  }  /* End for each server loop */

 

   rpc_binding_vector_free(&results, &st);  /* free binding vector */

   printf("************ End of Stats from BINOPS Servers ***********\n\n");

   exit(0);

}  /* end main() */

 

 


FILE:DCEPORT.H

/*++

 

Copyright (c) 1993-1994 Microsoft Corporation

 

Module Name:

 

    dceport.h

 

Abstract:

 

    Include file defining types and macros which map DCE RPC APIs to

    Microsoft RPC APIs.  Useful when porting DCE RPC applications to MS RPC.

 

--*/

 

#ifndef DCEPORT_H

#define DCEPORT_H

 

#ifdef __cplusplus

extern "C" {

#endif

 

/*

** Define various idl types

*/

#define idl_char                unsigned char

#define idl_boolean             unsigned char

#define idl_byte                unsigned char

#define idl_small_int           char

#define idl_usmall_int          unsigned char

#define idl_short_int           signed short

#define idl_ushort_int          unsigned short

#define idl_long_int            long

#define idl_ulong_int           unsigned long

#define boolean32               unsigned long

#define unsigned32              unsigned long

#define unsigned16              unsigned short

#define idl_true                1

#define idl_false               0

#define unsigned_char_t         unsigned char

typedef unsigned char __RPC_FAR *unsigned_char_p_t;

typedef void __RPC_FAR          *idl_void_p_t;

 

#ifndef _ERROR_STATUS_T_DEFINED

typedef unsigned long error_status_t;

#define _ERROR_STATUS_T_DEFINED

#endif

 

/*

** Define various DCE RPC types

*/

#define rpc_if_handle_t             RPC_IF_HANDLE

#define rpc_ns_handle_t             RPC_NS_HANDLE

#define rpc_authz_handle_t          RPC_AUTHZ_HANDLE

#define rpc_auth_identity_handle_t  RPC_AUTH_IDENTITY_HANDLE

#define rpc_sm_thread_handle_t      RPC_SS_THREAD_HANDLE

#define rpc_mgr_epv_t               RPC_MGR_EPV __RPC_FAR *

#define rpc_object_inq_fn_t         RPC_OBJECT_INQ_FN __RPC_FAR *

#define rpc_auth_key_retrieval_fn_t RPC_AUTH_KEY_RETRIEVAL_FN

#define rpc_mgmt_authorization_fn_t RPC_MGMT_AUTHORIZATION_FN

 

/*

** Define rpc_binding_vector_t to match DCE

*/

#ifdef rpc_binding_vector_t

#undef rpc_binding_vector_t

#endif

 

typedef struct

{

     unsigned long           count;

     handle_t                binding_h[1];

} rpc_binding_vector_t, __RPC_FAR *rpc_binding_vector_p_t;

 

/*

** Define rpc_protseq_vector_t to match DCE

*/

 

typedef struct

{

    unsigned long           count;

    unsigned char *         protseq[1];

} rpc_protseq_vector_t, __RPC_FAR *rpc_protseq_vector_p_t;

 

/*

** Define rpc_stats_vector_t to match DCE

*/

 

typedef struct

{

    unsigned long           count;

    unsigned long           stats[1];

} rpc_stats_vector_t, __RPC_FAR *rpc_stats_vector_p_t;

 

/*

** Define uuid_t to match DCE

*/

#ifdef uuid_t

#undef uuid_t

#endif

 

typedef struct

{

    unsigned long            time_low;

    unsigned short           time_mid;

    unsigned short           time_hi_and_version;

    unsigned char            clock_seq_hi_and_reserved;

    unsigned char            clock_seq_low;

    unsigned char            node[6];

} uuid_t, __RPC_FAR *uuid_p_t;

 

/*

** Define uuid_vector_t to match DCE

*/

#ifdef uuid_vector_t

#undef uuid_vector_t

#endif

 

typedef struct

{

     unsigned long           count;

     uuid_p_t                uuid[1];

} uuid_vector_t, __RPC_FAR *uuid_vector_p_t;

 

/*

** Define rpc_if_id_t and rpc_if_id_p_t to match DCE

*/

 

typedef struct

{

    uuid_t                   uuid;

    unsigned short           vers_major;

    unsigned short           vers_minor;

} rpc_if_id_t, __RPC_FAR *rpc_if_id_p_t;

 

/*

** Define rpc_if_id_vector_t to match DCE

*/

 

typedef struct

{

    unsigned long           count;

    rpc_if_id_p_t           if_id[1];

} rpc_if_id_vector_t, __RPC_FAR *rpc_if_id_vector_p_t;

 

/*

** The MinThreads parameters to RpcServerListen()

** is not part of the DCE API rpc_server_listen().

** This is the default value.

*/

 

#define rpc_c_listen_min_threads_default 1

 

/*

** Define various constants

*/

#define rpc_c_ns_syntax_default            RPC_C_NS_SYNTAX_DEFAULT

#define rpc_c_ns_syntax_dce                RPC_C_SYNTAX_DCE

#define rpc_c_ns_default_exp_age           RPC_C_DEFAULT_EXP_AGE

#define rpc_c_protseq_max_reqs_default     RPC_C_PROTSEQ_MAX_REQS_DEFAULT

#define rpc_c_protseq_max_calls_default    RPC_C_PROTSEQ_MAX_REQS_DEFAULT

#define rpc_c_listen_max_calls_default     RPC_C_LISTEN_MAX_CALLS_DEFAULT

#define rpc_c_ep_all_elts                  RPC_C_EP_ALL_ELTS

#define rpc_c_ep_match_by_if               RPC_C_EP_MATCH_BY_IF

#define rpc_c_ep_match_by_obj              RPC_C_EP_MATCH_BY_OBJ

#define rpc_c_ep_match_by_both             RPC_C_EP_MATCH_BY_BOTH

#define rpc_c_vers_all                     RPC_C_VERS_ALL

#define rpc_c_vers_compatible              RPC_C_VERS_COMPATIBLE

#define rpc_c_vers_exact                   RPC_C_VERS_EXACT

#define rpc_c_vers_major_only              RPC_C_VERS_MAJOR_ONLY

#define rpc_c_vers_upto                    RPC_C_VERS_UPTO

#define rpc_c_profile_default_elt          RPC_C_PROFILE_DEFAULT_ELT

#define rpc_c_profile_all_elts             RPC_C_PROFILE_ALL_ELTS

#define rpc_c_profile_match_by_if          RPC_C_PROFILE_MATCH_BY_IF

#define rpc_c_profile_match_by_mbr         RPC_C_PROFILE_MATCH_BY_MBR

#define rpc_c_profile_match_by_both        RPC_C_PROFILE_MATCH_BY_BOTH

#define rpc_c_binding_min_timeout          RPC_C_BINDING_MIN_TIMEOUT

#define rpc_c_binding_default_timeout      RPC_C_BINDING_DEFAULT_TIMEOUT

#define rpc_c_binding_max_timeout          RPC_C_BINDING_MAX_TIMEOUT

#define rpc_c_binding_infinite_timeout     RPC_C_BINDING_INFINITE_TIMEOUT

#define rpc_c_stats_calls_in               RPC_C_STATS_CALLS_IN

#define rpc_c_stats_calls_out              RPC_C_STATS_CALLS_OUT

#define rpc_c_stats_pkts_in                RPC_C_STATS_PKTS_IN

#define rpc_c_stats_pkts_out               RPC_C_STATS_PKTS_OUT

#define rpc_c_mgmt_inq_if_ids              RPC_C_MGMT_INQ_IF_IDS

#define rpc_c_mgmt_inq_princ_name          RPC_C_MGMT_INQ_PRINC_NAME

#define rpc_c_mgmt_inq_stats               RPC_C_MGMT_INQ_STATS

#define rpc_c_mgmt_inq_server_listen       RPC_C_MGMT_INQ_SERVER_LISTEN

#define rpc_c_mgmt_stop_server_listen      RPC_C_MGMT_STOP_SERVER_LISTEN

#define rpc_c_mgmt_cancel_infinite_timeout RPC_C_CANCEL_INFINITE_TIMEOUT

 

/*

** Define DCE API equivalents

*/

#define rpc_binding_copy(source,dest,status) \

                *(status) = RpcBindingCopy(source,dest)

 

#define rpc_binding_free(binding,status) *(status) = RpcBindingFree(binding)

 

#define rpc_binding_from_string_binding(string_binding,binding,status) \

                *(status) = RpcBindingFromStringBinding(string_binding,binding)

 

#define rpc_binding_inq_auth_client(binding,privs,princ_name,protect_level, \

                authn_svc,authz_svc,status) \

                *(status) = RpcBindingInqAuthClient(binding,privs,princ_name, \

                protect_level,authn_svc,authz_svc)

 

#define rpc_binding_inq_auth_info(binding,princ_name,protect_level,\

                authn_svc,auth_identity,authz_svc,status) \

                *(status) = RpcBindingInqAuthInfo(binding,princ_name, \

                protect_level,authn_svc,auth_identity,authz_svc)

 

#define rpc_binding_inq_object(binding,object_uuid,status) \

                *(status) = RpcBindingInqObject(binding,\

                (UUID __RPC_FAR *)object_uuid)

 

#define rpc_binding_reset(binding,status) *(status) = RpcBindingReset(binding)

 

#define rpc_binding_server_from_client(cbinding,sbinding,status) \

                *(status) = RpcBindingServerFromClient(cbinding,sbinding)

 

#define rpc_binding_set_auth_info(binding,princ_name,protect_level,\

                authn_svc,auth_identity,authz_svc,status) \

                *(status) = RpcBindingSetAuthInfo(binding,princ_name,\

                protect_level,authn_svc,auth_identity,authz_svc)

 

#define rpc_binding_set_object(binding,object_uuid,status) \

                *(status) = RpcBindingSetObject(binding,\

                (UUID __RPC_FAR *)object_uuid)

 

#define rpc_binding_to_string_binding(binding,string_binding,status) \

                *(status) = RpcBindingToStringBinding(binding,string_binding)

 

#define rpc_binding_vector_free(binding_vector,status) \

                *(status) = RpcBindingVectorFree(\

                (RPC_BINDING_VECTOR __RPC_FAR * __RPC_FAR *)binding_vector)

 

#define rpc_ep_register(if_spec,binding_vec,object_uuid_vec,annotation,\

                status)\

                *(status) = RpcEpRegister(if_spec,\

                (RPC_BINDING_VECTOR __RPC_FAR *)binding_vec, \

                (UUID_VECTOR __RPC_FAR *)object_uuid_vec, annotation)

 

#define rpc_ep_register_no_replace(if_spec,binding_vec,object_uuid_vec,\

                annotation,status) \

                *(status) = RpcEpRegisterNoReplace(if_spec,\

                (RPC_BINDING_VECTOR __RPC_FAR *)binding_vec,\

                (UUID_VECTOR __RPC_FAR *)object_uuid_vec,annotation)

 

#define rpc_ep_resolve_binding(binding_h,if_spec,status) \

                *(status) = RpcEpResolveBinding(binding_h,if_spec)

 

#define rpc_ep_unregister(if_spec,binding_vec,object_uuid_vec,status) \

                *(status) = RpcEpUnregister(if_spec,\

                (RPC_BINDING_VECTOR __RPC_FAR *)binding_vec,\

                (UUID_VECTOR __RPC_FAR *)object_uuid_vec)

 

#define rpc_if_id_vector_free(if_id_vector,status) \

                *(status) = RpcIfIdVectorFree(\

                (RPC_IF_ID_VECTOR __RPC_FAR * __RPC_FAR *)if_id_vector)

 

#define rpc_if_inq_id(if_spec,if_id,status) \

                *(status) = RpcIfInqId(if_spec,(RPC_IF_ID __RPC_FAR *)if_id)

 

#define rpc_if_register_auth_info(if_spec,princ_name,protect_level,\

                authn_svc,auth_identity,authz_svc,status) \

                *(status) = RpcIfRegisterAuthInfo(if_spec,princ_name,\

                protect_level,authn_svc,auth_identity,authz_svc)

 

#define rpc_mgmt_ep_elt_inq_begin(ep_binding,inquiry_type,if_id,vers_option,\

                object_uuid,inquiry_context,status) \

                *(status) = RpcMgmtEpEltInqBegin(ep_binding,inquiry_type,if_id,\

                vers_option,object_uuid,inquiry_context)

 

#define rpc_mgmt_ep_elt_inq_done(inquiry_context,status) \

                *(status) = RpcMgmtEpEltInqDone(inquiry_context)

 

#define rpc_mgmt_ep_elt_inq_next(inquiry_context,if_id,binding,object_uuid,\

                annotation,status) \

                *(status) = RpcMgmtEpEltInqNext(inquiry_context,if_id,binding,\

                object_uuid,annotation)

 

#define rpc_mgmt_ep_unregister(ep_binding,if_id,binding,object_uuid,status) \

                *(status) = RpcMgmtEpUnregister(ep_binding,if_id,binding,\

                object_uuid)

 

#define rpc_mgmt_inq_com_timeout(binding,timeout,status) \

                *(status) = RpcMgmtInqComTimeout(binding,timeout)

 

#define rpc_mgmt_inq_dflt_protect_level(authn_svc,level,status) \

                *(status) = RpcMgmtInqDefaultProtectLevel(authn_svc,level)

 

#define rpc_mgmt_inq_if_ids(binding,if_id_vector,status) \

                *(status) = RpcMgmtInqIfIds((bindings),\

                (RPC_IF_ID_VECTOR __RPC_FAR * __RPC_FAR *)(if_id_vector))

 

#define rpc_mgmt_inq_server_princ_name(binding,authn_svc,princ_name,status) \

                *(status) = RpcMgmtInqServerPrincName(binding,authn_svc,\

                princ_name)

 

#define rpc_mgmt_inq_stats(binding,statistics,status) \

                *(status) = RpcMgmtInqStats(binding,\

                (RPC_STATS_VECTOR __RPC_FAR * __RPC_FAR *)statistics)

 

#define rpc_mgmt_is_server_listening(binding,status) \

                ( ((*(status) = RpcMgmtIsServerListening(binding)) == RPC_S_OK) \

                ? (1) : (*(status) == RPC_S_NOT_LISTENING) \

                ? (*(status) = RPS_S_OK, 0) : (0) )

 

#define rpc_mgmt_set_authorization_fn(authz_fn,status) \

                *(status) = RpcMgmtSetAuthorizathionFn(authz_fn)

 

#define rpc_mgmt_set_cancel_timeout(seconds,status) \

                *(status) = RpcMgmtSetCancelTimeout(seconds)

 

#define rpc_mgmt_set_com_timeout(binding,timeout,status) \

                *(status) = RpcMgmtSetComTimeout(binding,timeout)

 

#define rpc_mgmt_set_server_stack_size(size,status) \

                *(status) = RpcMgmtSetServerStackSize(size)

 

#define rpc_mgmt_stats_vector_free(stats,status) \

                *(status) = RpcMgmtStatsVectorFree(\

                (RPC_STATS_VECTOR __RPC_FAR * __RPC_FAR *)stats)

 

#define rpc_mgmt_stop_server_listening(binding,status) \

                *(status) = RpcMgmtStopServerListening(binding)

 

#define rpc_network_inq_protseqs(prots,status) \

                *(status) = RpcNetworkInqProtseqs(\

                (RPC_PROTSEQ_VECTOR __RPC_FAR * __RPC_FAR *)prots)

 

#define rpc_network_is_protseq_valid(protseq,status) \

                *(status) = RpcNetworkIsProtseqValid(protseq)

 

/*

** Define NSI equivalents

*/

#define rpc_ns_binding_export(name_syntax,entry_name,if_spec,\

                binding_vector, uuid_vector,status) \

                *(status) = RpcNsBindingExport(name_syntax,entry_name,\

                if_spec, (RPC_BINDING_VECTOR *)binding_vector,\

                (UUID_VECTOR __RPC_FAR *)uuid_vector)

 

#define rpc_ns_binding_import_begin(name_syntax,entry_name,if_spec,\

                object_uuid,import_context,status) \

                *(status) = RpcNsBindingImportBegin(name_syntax,entry_name,\

                if_spec,(UUID __RPC_FAR *)object_uuid,import_context)

 

#define rpc_ns_binding_import_done(import_context,status) \

                *(status) = RpcNsBindingImportDone(import_context)

 

#define rpc_ns_binding_import_next(import_context,binding,status) \

                *(status) = RpcNsBindingImportNext(import_context,binding)

 

#define rpc_ns_binding_inq_entry_name(binding,name_syntax,entry_name,status)\

                *(status) = RpcNsBindingInqEntryName(binding,name_syntax,\

                entry_name)

 

#define rpc_ns_binding_lookup_begin(name_syntax,entry_name,if_spec,\

                object_uuid,max_count,lookup_context,status) \

                *(status) = RpcNsBindingLookupBegin(name_syntax,entry_name,\

                if_spec,(UUID __RPC_FAR *)object_uuid,max_count,lookup_context)

 

#define rpc_ns_binding_lookup_done(lookup_context,status) \

                *(status) = RpcNsBindingLookupDone(lookup_context)

 

#define rpc_ns_binding_lookup_next(lookup_context,binding_vector,status) \

                *(status) = RpcNsBindingLookupNext(lookup_context, \

                (RPC_BINDING_VECTOR __RPC_FAR * __RPC_FAR *)binding_vector)

 

#define rpc_ns_binding_select(binding_vector,binding,status) \

                *(status) = RpcNsBindingSelect(\

                (RPC_BINDING_VECTOR __RPC_FAR *)binding_vector,binding)

 

#define rpc_ns_binding_unexport(name_syntax,entry_name,if_spec,\

                uuid_vector,status) \

                *(status) = RpcNsBindingUnexport(name_syntax,entry_name,\

                if_spec, (UUID_VECTOR __RPC_FAR *)uuid_vector)

 

#define rpc_ns_entry_expand_name(name_syntax,entry_name,expanded_name,\

                status)\

                *(status) = RpcNsEntryExpandName(name_syntax,entry_name,\

                expanded_name)

 

#define rpc_ns_entry_object_inq_begin(name_syntax,entry_name,\

                inquiry_context,status)\

                *(status) = RpcNsEntryObjectInqBegin(name_syntax,\

                entry_name,inquiry_context)

 

#define rpc_ns_entry_object_inq_done(inquiry_context,status) \

                *(status) = RpcNsEntryObjectInqDone(inquiry_context)

 

#define rpc_ns_entry_object_inq_next(inquiry_context,object_uuid,status) \

                *(status) = RpcNsEntryObjectInqNext(inquiry_context,\

                (UUID __RPC_FAR *)object_uuid)

 

#define rpc_ns_group_delete(name_syntax,group_name,status) \

                *(status) = RpcNsGroupDelete(name_syntax,group_name)

 

#define rpc_ns_group_mbr_add(name_syntax,group_name,member_name_syntax,\

                member_name,status) \

                *(status) = RpcNsGroupMbrAdd(name_syntax,group_name,\

                member_name_syntax,member_name)

 

#define rpc_ns_group_mbr_inq_begin(name_syntax,group_name,member_name_syntax,\

                inquiry_context,status) \

                *(status) = RpcNsGroupMbrInqBegin(name_syntax,group_name,\

                member_name_syntax,inquiry_context)

 

#define rpc_ns_group_mbr_inq_done(inquiry_context,status) \

                *(status) = RpcNsGroupMbrInqDone(inquiry_context)

 

#define rpc_ns_group_mbr_inq_next(inquiry_context,member_name,status) \

                *(status) = RpcNsGroupMbrInqNext(inquiry_context,member_name)

 

#define rpc_ns_group_mbr_remove(name_syntax,group_name,member_name_syntax,\

                member_name,status) \

                *(status) = RpcNsGroupMbrRemove(name_syntax,group_name,\

                member_name_syntax,member_name)

 

#define rpc_ns_mgmt_binding_unexport(name_syntax,entry_name,if_id,vers_option,\

                uuid_vector,status) \

                *(status) = RpcNsMgmtBindingUnexport(name_syntax,entry_name,\

                (RPC_IF_ID __RPC_FAR *)if_id,vers_option,\

                (UUID_VECTOR __RPC_FAR *)uuid_vector)

 

#define rpc_ns_mgmt_entry_create(name_syntax,entry_name,status) \

                *(status) = RpcNsMgmtEntryCreate(name_syntax,entry_name)

 

#define rpc_ns_mgmt_entry_delete(name_syntax,entry_name,status) \

                *(status) = RpcNsMgmtEntryDelete(name_syntax,entry_name)

 

#define rpc_ns_mgmt_entry_inq_if_ids(name_syntax,entry_name,if_id_vector,\

                status) \

                *(status) = RpcNsMgmtEntryInqIfIds(name_syntax,entry_name,\

                (RPC_IF_ID_VECTOR __RPC_FAR * __RPC_FAR *)if_id_vector)

 

#define rpc_ns_mgmt_handle_set_exp_age(ns_handle,expiration_age,status) \

                *(status) = RpcNsMgmtHandleSetExpAge(ns_handle,expiration_age)

 

#define rpc_ns_mgmt_inq_exp_age(expiration_age,status) \

                *(status) = RpcNsMgmtInqExpAge(expiration_age)

 

#define rpc_ns_mgmt_set_exp_age(expiration_age,status) \

                *(status) = RpcNsMgmtSetExpAge(expiration_age)

 

#define rpc_ns_profile_delete(name_syntax,profile_name,status) \

                *(status) = RpcNsProfileDelete(name_syntax,profile_name)

 

#define rpc_ns_profile_elt_add(name_syntax,profile_name,if_id,\

                member_name_syntax,member_name,priority,annotation,status) \

                *(status) = RpcNsProfileEltAdd(name_syntax,profile_name,\

                (RPC_IF_ID __RPC_FAR *)if_id,member_name_syntax,member_name,\

                priority,annotation)

 

#define rpc_ns_profile_elt_inq_begin(name_syntax,profile_name,inquiry_type,\

                if_id,if_vers_option,member_name_syntax,\

                member_name,inquiry_context,status) \

                *(status) = RpcNsProfileEltInqBegin(name_syntax,profile_name,\

                inquiry_type,(RPC_IF_ID __RPC_FAR *)if_id,if_vers_option,\

                member_name_syntax,member_name,inquiry_context)

 

#define rpc_ns_profile_elt_inq_done(inquiry_context,status) \

                *(status) = RpcNsProfileEltInqDone(inquiry_context)

 

#define rpc_ns_profile_elt_inq_next(inquiry_context,if_id,member_name,\

                priority,annotation,status) \

                *(status) = RpcNsProfileEltInqNext(inquiry_context,\

                (RPC_IF_ID __RPC_FAR *)if_id,member_name,priority,annotation)

 

#define rpc_ns_profile_elt_remove(name_syntax,profile_name,if_id,\

                member_name_syntax,member_name,status) \

                *(status) = RpcNsProfileEltRemove(name_syntax,profile_name,\

                (RPC_IF_ID __RPC_FAR *)if_id,member_name_syntax,member_name)

 

#define rpc_object_inq_type(object_uuid,type_uuid,status) \

                *(status) = RpcObjectInqType((UUID __RPC_FAR *)object_uuid,\

                (UUID __RPC_FAR *)type_uuid)

 

#define rpc_object_set_inq_fn(inq_fn,status) \

                *(status) = RpcObjectSetInqFn(inq_fn)

 

#define rpc_object_set_type(object_uuid,type_uuid,status) \

                *(status) = RpcObjectSetType((UUID __RPC_FAR *)object_uuid,\

                (UUID __RPC_FAR *)type_uuid)

 

#define rpc_protseq_vector_free(protseq_vector,status) \

                *(status) = RpcProtseqVectorFree( \

                (RPC_PROTSEQ_VECTOR __RPC_FAR * __RPC_FAR *)protseq_vector)

 

#define rpc_server_inq_bindings(binding_vector,status) \

                *(status) = RpcServerInqBindings(\

                (RPC_BINDING_VECTOR __RPC_FAR * __RPC_FAR *)binding_vector)

 

#define rpc_server_inq_if(if_spec,type_uuid,mgr_epv,status) \

                *(status) = RpcServerInqIf(if_spec,(UUID __RPC_FAR *)type_uuid,\

                (RPC_MGR_EPV __RPC_FAR *)mgr_epv)

 

#define rpc_server_listen(max_calls,status) \

                *(status) = RpcServerListen(rpc_c_listen_min_threads_default,\

                max_calls,0)

 

#define rpc_server_register_auth_info(princ_name,auth_svc,get_key_func,arg,\

                status) \

                *(status) = RpcServerRegisterAuthInfo(princ_name,auth_svc,\

                get_key_func,arg)

 

#define rpc_server_register_if(if_spec,type_uuid,mgr_epv,status) \

                *(status) = RpcServerRegisterIf(if_spec,\

                (UUID __RPC_FAR *)type_uuid,(RPC_MGR_EPV __RPC_FAR *)mgr_epv)

 

#define rpc_server_unregister_if(if_spec,type_uuid,status) \

                *(status) = RpcServerUnregisterIf(if_spec,(UUID *)type_uuid,0)

 

#define rpc_server_use_all_protseqs(max_call_requests,status) \

                *(status) = RpcServerUseAllProtseqs(max_call_requests,0)

 

#define rpc_server_use_all_protseqs_if(max_call_requests,if_spec,status) \

                *(status) = RpcServerUseAllProtseqsIf(max_call_requests,\

                if_spec,0)

 

#define rpc_server_use_protseq(protseq,max_call_requests,status) \

                *(status) = RpcServerUseProtseq(protseq,max_call_requests,0)

 

#define rpc_server_use_protseq_ep(protseq,max_call_requests,endpoint,status)\

                *(status) = RpcServerUseProtseqEp(protseq,max_call_requests,\

                endpoint,0)

 

#define rpc_server_use_protseq_if(protseq,max_call_requests,if_spec,status) \

                *(status) = RpcServerUseProtseqIf(protseq,max_call_requests,\

                if_spec,0)

 

#define rpc_sm_alloce(size,status) *(status) = RpcSmAllocate(size)

 

#define rpc_sm_client_free(ptr,status) *(status) = RpcSmClientFree(ptr)

 

#define rpc_sm_destroy_client_context(context,status) \

                *(status) = RpcSmDestroyClientContext(context)

 

#define rpc_sm_disable_allocate(status) *(status) = RpcSmDisableAllocate()

 

#define rpc_sm_enable_allocate(status) *(status) = RpcSmEnableAllocate()

 

#define rpc_sm_free(ptr,status) *(status) = RpcSmFree(ptr)

 

#define rpc_sm_get_thread_handle(status) RpcSmGetThreadHandle(status)

 

#define rpc_sm_set_client_alloc_free(alloc,free,status) \

                *(status) = RpcSmSetClientAllocFree(alloc,free)

 

#define rpc_sm_set_thread_handle(id,status) \

                *(status) = RpcSmSetThreadHandle(id)

 

#define rpc_sm_swap_client_alloc_free(alloc,free,old_alloc,old_free,status) \

                *(status) = RpcSmSwapClientAllocFree(alloc,free \

                old_alloc, old_free)

 

#define rpc_string_binding_compose(object_uuid,protseq,netaddr,endpoint,\

                options,binding,status) \

                *(status) = RpcStringBindingCompose(object_uuid,protseq,\

                netaddr,endpoint,options,binding)

 

#define rpc_string_binding_parse(string_binding,object_uuid,protseq,netaddr,\

                endpoint,options,status) \

                *(status) = RpcStringBindingParse(string_binding,\

                object_uuid,protseq,netaddr,endpoint,options)

 

#define rpc_string_free(string,status) *(status) = RpcStringFree(string)

 

#define uuid_compare(uuid1,uuid2,status) \

                UuidCompare((UUID __RPC_FAR *)(uuid1),\

                            (UUID __RPC_FAR *)(uuid2),(status))

 

#define uuid_create(uuid,status) \

                *(status) = UuidCreate((UUID __RPC_FAR *)uuid)

 

#define uuid_create_nil(uuid,status) \

                *(status) = UuidCreateNil((UUID __RPC_FAR *)uuid)

 

#define uuid_equal(uuid1,uuid2,status) \

                UuidEqual((UUID __RPC_FAR *)(uuid1), \

                          (UUID __RPC_FAR *)(uuid2), (status))

 

#define uuid_from_string(string,uuid,status) \

                *(status) = UuidFromString(string,(UUID __RPC_FAR *)uuid)

 

#define uuid_hash(uuid,status) \

                UuidHash((UUID __RPC_FAR *)(uuid),(status))

 

#define uuid_is_nil(uuid,status) \

                UuidIsNil((UUID __RPC_FAR *)(uuid), (status))

 

#define uuid_to_string(uuid,string,status)\

                *(status) = UuidToString((UUID __RPC_FAR *)uuid,string)

 

 

#define true  1

#define false 0

 

/*

** Define exception handling equivalents

**

*/

#if defined (__RPC_WIN16__) || defined (__RPC_DOS__)

 

#define TRY                                       \

    {                                                \

    int _exception_mode_finally;                     \

    int _exception_code;                             \

    ExceptionBuff exception;                         \

    _exception_code = RpcSetException(&exception);   \

    if (!_exception_code)                            \

    {

 

#define CATCH_ALL                                 \

        _exception_mode_finally = false;             \

        RpcLeaveException();                         \

        }                                            \

        else                                         \

        {

/*

 * #define CATCH(X)                               \

 *   }else if ((unsigned long)RpcExceptionCode()==(unsigned long)X) {

 */

#define FINALLY                                   \

        _exception_mode_finally = true;              \

        RpcLeaveException();                         \

        } {

#define ENDTRY                                    \

          }                                               \

        if (_exception_mode_finally && _exception_code)  \

            RpcRaiseException(_exception_code);           \

        }

 

#endif /* WIN16 or DOS */

 

 

#if defined (__RPC_WIN32__)

#define TRY             try {

/*

 * #define CATCH(X)        \

 *                      } except (GetExceptionCode() == X ? \

 *                        EXCEPTION_EXECUTE_HANDLER : \

 *                        EXCEPTION_CONTINUE_SEARCH) {

 */

#define CATCH catch

#define CATCH_ALL       } except (EXCEPTION_EXECUTE_HANDLER) {

#define FINALLY         } finally {

#define ENDTRY          }

#endif /* WIN32 */

 

#define RAISE(v)   RpcRaiseException(v)

#define RERAISE    RpcRaiseException(RpcExceptionCode())

#define THIS_CATCH RpcExceptionCode()

 

/*

** DCE Status code mappings

*/

#ifndef rpc_s_ok

#define rpc_s_ok                        RPC_S_OK

#endif

#ifndef error_status_ok

#define error_status_ok                 RPC_S_OK

#endif

#define ept_s_cant_perform_op           EPT_S_CANT_PERFORM_OP

#define ept_s_invalid_entry             EPT_S_INVALID_ENTRY

#define ept_s_not_registered            EPT_S_NOT_REGISTERED

#define rpc_s_already_listening         RPC_S_ALREADY_LISTENING

#define rpc_s_already_registered        RPC_S_ALREADY_REGISTERED

#define rpc_s_binding_has_no_auth       RPC_S_BINDING_HAS_NO_AUTH

#define rpc_s_binding_imcomplete        RPC_S_BINDING_IMCOMPLETE

#define rpc_s_call_cancelled            RPC_S_CALL_CANCELLED

#define rpc_s_call_failed               RPC_S_CALL_FAILED

#define rpc_s_cant_bind_socket          RPC_S_CANNOT_BIND

#define rpc_s_cant_create_socket        RPC_S_CANT_CREATE_ENDPOINT

#define rpc_s_comm_failure              RPC_S_COMM_FAILURE

#define rpc_s_connect_no_resources      RPC_S_OUT_OF_RESOURCES

#define rpc_s_cthread_create_failed     RPC_S_OUT_OF_THREADS

#define rpc_s_endpoint_not_found        RPC_S_NO_ENDPOINT_FOUND

#define rpc_s_entry_already_exists      RPC_S_ENTRY_ALREADY_EXISTS

#define rpc_s_entry_not_found           RPC_S_ENTRY_NOT_FOUND

#define rpc_s_fault_addr_error          RPC_S_ADDRESS_ERROR

#define rpc_s_fault_fp_div_by_zero      RPC_S_FP_DIV_ZERO

#define rpc_s_fault_fp_overflow         RPC_S_FP_OVERFLOW

#define rpc_s_fault_fp_underflow        RPC_S_FP_UNDERFLOW

#define rpc_s_fault_int_div_by_zero     RPC_S_ZERO_DIVIDE

#define rpc_s_fault_invalid_bound       RPC_S_INVALID_BOUND

#define rpc_s_fault_invalid_tag         RPC_S_INVALID_TAG

#define rpc_s_fault_remote_no_memory    RPC_S_SERVER_OUT_OF_MEMORY

#define rpc_s_fault_unspec              RPC_S_CALL_FAILED

#define rpc_s_incomplete_name           RPC_S_INCOMPLETE_NAME

#define rpc_s_interface_not_found       RPC_S_INTERFACE_NOT_FOUND

#define rpc_s_internal_error            RPC_S_INTERNAL_ERROR

#define rpc_s_inval_net_addr            RPC_S_INVALID_NET_ADDR

#define rpc_s_invalid_arg               RPC_S_INVALID_ARG

#define rpc_s_invalid_binding           RPC_S_INVALID_BINDING

#define rpc_s_invalid_endpoint_format   RPC_S_INVALID_ENDPOINT_FORMAT

#define rpc_s_invalid_naf_id            RPC_S_INVALID_NAF_IF

#define rpc_s_invalid_name_syntax       RPC_S_INVALID_NAME_SYNTAX

#define rpc_s_invalid_rpc_protseq       RPC_S_INVALID_RPC_PROTSEQ

#define rpc_s_invalid_string_binding    RPC_S_INVALID_STRING_BINDING

#define rpc_s_invalid_timeout           RPC_S_INVALID_TIMEOUT

#define rpc_s_invalid_vers_option       RPC_S_INVALID_VERS_OPTION

#define rpc_s_max_calls_too_small       RPC_S_MAX_CALLS_TOO_SMALL

#define rpc_s_mgmt_op_disallowed        RPC_S_ACCESS_DENIED

#define rpc_s_name_service_unavailable  RPC_S_NAME_SERVICE_UNAVAILABLE

#define rpc_s_no_bindings               RPC_S_NO_BINDINGS

#define rpc_s_no_entry_name             RPC_S_NO_ENTRY_NAME

#define rpc_s_no_interfaces             RPC_S_NO_INTERFACES

#define rpc_s_no_interfaces_exported    RPC_S_NO_INTERFACES_EXPORTED

#define rpc_s_no_memory                 RPC_S_OUT_OF_MEMORY

#define rpc_s_no_more_elements          RPC_X_NO_MORE_ENTRIES

#define rpc_s_no_more_bindings          RPC_S_NO_MORE_BINDINGS

#define rpc_s_no_more_members           RPC_S_NO_MORE_MEMBERS

#define rpc_s_no_ns_permission          RPC_S_ACCESS_DENIED

#define rpc_s_no_princ_name             RPC_S_NO_PRINC_NAME

#define rpc_s_no_protseqs               RPC_S_NO_PROTSEQS

#define rpc_s_no_protseqs_registered    RPC_S_NO_PROTSEQS_REGISTERED

#define rpc_s_not_rpc_tower             RPC_S_CANNOT_SUPPORT

#define rpc_s_not_supported             RPC_S_CANNOT_SUPPORT

#define rpc_s_not_authorized            RPC_S_ACCESS_DENIED

#define rpc_s_nothing_to_unexport       RPC_S_NOTHING_TO_UNEXPORT

#define rpc_s_object_not_found          RPC_S_OBJECT_NOT_FOUND

#define rpc_s_protocol_error            RPC_S_PROTOCOL_ERROR

#define rpc_s_protseq_not_supported     RPC_S_PROTSEQ_NOT_SUPPORTED

#define rpc_s_server_too_busy           RPC_S_SERVER_TOO_BUSY

#define rpc_s_string_too_long           RPC_S_STRING_TOO_LONG

#define rpc_s_type_already_registered   RPC_S_TYPE_ALREADY_REGISTERED

#define rpc_s_unknown_authn_service     RPC_S_UNKNOWN_AUTHN_SERVICE

#define rpc_s_unknown_authz_service     RPC_S_UNKNOWN_AUTHZ_SERVICE

#define rpc_s_unknown_if                RPC_S_UNKNOWN_IF

#define rpc_s_unknown_mgr_type          RPC_S_UNKNOWN_MGR_TYPE

#define rpc_s_unknown_reject            RPC_S_CALL_FAILED_DNE

#define rpc_s_unsupported_name_syntax   RPC_S_UNSUPPORTED_NAME_SYNTAX

#define rpc_s_unsupported_type          RPC_S_UNSUPPORTED_TYPE

#define rpc_s_wrong_boot_time           RPC_S_CALL_FAILED_DNE

#define rpc_s_wrong_kind_of_binding     RPC_S_WRONG_KIND_OF_BINDING

#define uuid_s_ok                       RPC_S_OK

#define uuid_s_internal_error           RPC_S_INTERNAL_ERROR

#define uuid_s_invalid_string_uuid      RPC_S_INVALID_STRING_UUID

#define uuid_s_no_address               RPC_S_UUID_NO_ADDRESS

 

/*

** DCE Exception mappings

*/

 

#define rpc_x_comm_failure              RPC_S_COMM_FAILURE

#define rpc_x_connect_no_resources      RPC_S_OUT_OF_RESOURCES

#define rpc_x_entry_not_found           RPC_S_ENTRY_NOT_FOUND

#define rpc_x_incomplete_name           RPC_S_INCOMPLETE_NAME

#define rpc_x_invalid_arg               RPC_S_INVALID_ARG

#define rpc_x_invalid_binding           RPC_S_INVALID_BINDING

#define rpc_x_invalid_bound             RPC_X_INVALID_BOUND

#define rpc_x_invalid_endpoint_format   RPC_S_INVALID_ENDPOINT_FORMAT

#define rpc_x_invalid_naf_id            RPC_S_INVALID_NAF_IF

#define rpc_x_invalid_name_syntax       RPC_S_INVALID_NAME_SYNTAX

#define rpc_x_invalid_rpc_protseq       RPC_S_INVALID_RPC_PROTSEQ

#define rpc_x_invalid_tag               RPC_X_INVALID_TAG

#define rpc_x_invalid_timeout           RPC_S_INVALID_TIMEOUT

#define rpc_x_no_memory                 RPC_X_NO_MEMORY

#define rpc_x_object_not_found          RPC_S_OBJECT_NOT_FOUND

#define rpc_x_protocol_error            RPC_S_PROTOCOL_ERROR

#define rpc_x_protseq_not_supported     RPC_S_PROTSEQ_NOT_SUPPORTED

#define rpc_x_server_too_busy           RPC_S_SERVER_TOO_BUSY

#define rpc_x_ss_char_trans_open_fail   RPC_X_SS_CHAR_TRANS_OPEN_FAIL

#define rpc_x_ss_char_trans_short_file  RPC_X_SS_CHAR_TRANS_SHORT_FILE

#define rpc_x_ss_context_damaged        RPC_X_SS_CONTEXT_DAMAGED

#define rpc_x_ss_context_mismatch       RPC_X_SS_CONTEXT_MISMATCH

#define rpc_x_ss_in_null_context        RPC_X_SS_IN_NULL_CONTEXT

#define rpc_x_string_too_long           RPC_S_STRING_TOO_LONG

#define rpc_x_unknown_if                RPC_S_UNKNOWN_IF

#define rpc_x_unknown_mgr_type          RPC_S_UNKNOWN_MGR_TYPE

#define rpc_x_unsupported_name_syntax   RPC_S_UNSUPPORTED_NAME_SYNTAX

#define rpc_x_unsupported_type          RPC_S_UNSUPPORTED_TYPE

#define rpc_x_wrong_boot_time           RPC_S_CALL_FAILED_DNE

#define rpc_x_wrong_kind_of_binding     RPC_S_WRONG_KIND_OF_BINDING

#define uuid_x_internal_error           RPC_S_INTERNAL_ERROR

 

#ifdef __cplusplus

}

#endif

 

#endif /* DCEPORT_H */

 

 


FILE:MAKEFILE

############################################################################

# Makefile for binopc and binops client/server DCE application program

#

# Author:   G.K. Springer at U of MO - Columbia

# Date:     June 1991

# Node:     condor.cs.missouri.edu

# Place:    Computer Science Department, University of Missouri-Columbia

#

# Purpose:  Demonstrate the coding for a simple DCE RPC application.

#           The application makes 100 requests to a server to perform 50

#           additions and 50 subtractions in sequence to see the effect

#           of making these requests across the network.

#

# Function: Client calls upon a server to compute either the addition or

#           or subtraction of two numbers passed as parameters in a RPC

#           call.  The RPC functions return the result to the caller.

#           This application uses a server that exports two RPC functions;

#           an addition function and a subtraction function.  The client

#           performs a specifiable number of calls to the add function and

#           the same number of calls to the subtract function in order to

#           time the average amount of time needed to complete a single call.

#           The results of the computations and the time/call are written

#           to stdout.

#

# Update Log:

#   6/28/91 - Corrected Makefile to support building individual components

#   3/26/93 - Upgraded code to handle multiple versions of interface and

#             set makefile so it can handle makes on different platforms.

#             For Apollo:  make

#                 DEC:     make GENSYS=-DDEC

#                 RS/6000: make GENSYS=-DIBMRISC LIB2=-lbsd

#  10/25/93 - Changes to build code for a DCE system

#             Code to build system on different platforms is separated

#             into separate makefiles so the application can be created

#             on multiple platforms:

#             where:  platform is one of [alpha, cray, mips or rs6000]

#             if a particular component is to be built, use the MK

#             macro of Make to specify the component that is to be built.

#

#             For example: make  alpha     builds entire system

#                          make  alpha MK=clean     cleans up after build

#                          make  cray  MK=binops    builds server on cray

#   4/22/95 - JimR: Completed section for Win32 builds.  Note that we are

#             dependent on the tm.exe utility.

#   2/26/98 - JimR: Merged in old Microsoft native way to build (WIN32RAW).

#

############################################################################

 

 

############################################################################

## This is a heuristic to make sure that WIN32 is set when building on NT ##

!ifdef CPU

WIN32=1

!endif

############################################################################

 

 

############################################################################

## This is necessary to set specific flags for PC environments            ##

!ifdef WIN32

CFLAGS=/c /GX /I. /I.. /I..\..\include /I..\..\logger /I..\..\service -D_X86_=1 -G3 -Gz -DDCENT -Didl_char=char -D_MSDOS -DEP -DWIN32=1 /nologo /Zp1

 

!      ifdef DEBUG

CFLAGS=$(CFLAGS) -DDEBUG -Od -Zi

!      endif  // DEBUG

 

!      ifdef NOCERT

CFLAGS=$(CFLAGS) -DNOCERT

!      endif  // NOCERT

 

!      ifdef NODAEMON

CFLAGS=$(CFLAGS) -DNODAEMON

!      endif  // NODAEMON

 

!endif // WIN32

############################################################################

 

 

!ifdef WIN32

default:

       @echo.

       @echo Making Binop Demo Application

       @echo.

       @echo No system specified for the make.

       @echo.

       @echo Usage:  make  sysname  [MK=components_to_build]

       @echo where:

       @echo sysname is one of [ alpha cray mips rs6000 win32 win32raw]

       @echo.

!else

default:

       @echo ' '

       @echo 'Making Binop Demo Application'

       @echo ' '

       @echo '  No system specified for the make.'

       @echo ' '

       @echo '     Usage:  make  sysname  [MK=components_to_build]'

       @echo '        where:'

       @echo '          sysname is one of [ alpha cray mips rs6000 win32]'

       @echo ' '

!endif

 

# Make the code on WIN32 platforms (Windows 95 and NT), assuming full DCE support

WIN32: makefile.bin

       @tm start

       @echo Build Binop Demo on WIN32

       @if not exist build.win md build.win

       @if not exist ..\build.wbn md ..\build.wbn

       @cd build.win

       @echo building with these CFLAGS=$(CFLAGS)

       @$(MAKE) /nologo -f ..\makefile.bin \

      WIN32=1 \

      TSRC=.. \

      T1=..\..\build.wbn \

      IDL=idl \

          IDLFLAGS= \

              CFLAGS="$(CFLAGS)" \

              LINKFLGS= \

      LIBS="pthreads.lib libdce.lib wsock32.lib advapi32.lib" \

      LIB2= \

      GENSYS=WIN32

       @echo Build on WIN32 complete

       @tm stop

 

# Make the code on WIN32 platforms (Windows 95 and NT), assuming full DCE support

WIN32RAW: makefile.bin

       @tm start

       @echo Build Binop Demo on WIN32RAW

       @if not exist build.win md build.win

       @if not exist ..\build.wbn md ..\build.wbn

       @cd build.win

       @echo building with these CFLAGS=$(CFLAGS)

       @$(MAKE) /nologo -f ..\makefile.bin \

      WIN32RAW=1 \

      WIN32=1 \

      TSRC=.. \

      T1=..\..\build.wbn \

      IDL=midl \

          IDLFLAGS=/osf \

              CFLAGS="$(CFLAGS) /DWIN32RAW" \

              LINKFLGS= \

      LIBS=rpcrt4.lib \

      LIB2= \

      GENSYS=WIN32

       @echo Build on WIN32RAW complete

       @tm stop

 

# Make the code on ALPHA platforms

alpha: Makefile.bindemo

       @echo

       @echo Build Binop Demo on ALPHA - `date`

       @if [ ! -d "Build.alpha" ] ; then mkdir Build.alpha ; fi ;

       @if [ ! -d "Build.abin" ] ; then ln -s ../../bin Build.abin ; fi ;

       @cd Build.alpha ;\

         $(MAKE) $(MFLAGS) -f ../Makefile.bindemo \

           TSRC='..' \

          T1='../Build.abin' \

           IDL=/usr/bin/idl \

          IDLFLAGS='-v -keep c_source -no_cpp' \

           CFLAGS='-c -DLOG -Dalpha -D_SHARED_LIBRARIES -I. -I.. -I../../include -D_REENTRANT -w' \

           LIBS='-L../Build.abin -llogger -lmuns -ldce -lpthreads -lc_r -lmach -lm' \

           LIB2='' \

           GENSYS=alpha \

           $(MK)

       @echo Build on ALPHA complete - `date`

 

# Make the code on Cray C90 at PSC

cray:  Makefile.bindemo

       @echo

       @echo Build Binop Demo on CRAY - `date`

       @if [ ! -d "Build.cray" ] ; then mkdir Build.cray ; fi ;

       @if [ ! -d "Build.cbin" ] ; then ln -s ../../bin Build.cbin ; fi ;

       @cd Build.cray ;\

         $(MAKE) $(MFLAGS) -f ../Makefile.bindemo \

          TSRC='..' \

          T1='../Build.cbin' \

          IDL=/opt/dcelocal/bin/idl \

          IDLFLAGS='-v -keep c_source -no_cpp' \

          CFLAGS='-c -std1 -DLOG -Dcray -DNODAEMON -I. -I/usr/include/dce -I.. -I../../include -w' \

          LIBS='-L../Build.cbin -llogger -lmuns -ldce' \

          LIB2='' \

          GENSYS=cray \

           $(MK)

       @echo Build on CRAY complete - `date`

 

# Make the code on RS6000

rs6000:       Makefile.bindemo

       @echo

       @echo Build Binop Demo on RS6000 - `date`

       @if [ ! -d "Build.rs6000" ] ; then mkdir Build.rs6000 ; fi ;

       @if [ ! -d "Build.rbin" ] ; then ln -s ../../bin Build.rbin ; fi ;

       @cd Build.rs6000 ;\

         $(MAKE) $(MFLAGS) -f ../Makefile.bindemo \

          TSRC='..' \

          T1=../Build.rbin \

          IDL=/usr/bin/idl \

          IDLFLAGS='-v -keep c_source -I/usr/include/dce -no_cpp' \

          CFLAGS='-c -Dunix -qlanglvl=ansi -D_ALL_SOURCE -D_ANSI_C_SOURCE -I/usr/include/dce -I. -I.. -I../../include -w' \

          CC=/bin/xlc_r \

          LIBS='-L/usr/lib -L. -L../Build.rbin -lmuns -ldce' \

          LIB2='-lXm -lXt -lX11' \

          GENSYS=rs6000 \

          $(MK)

       @echo Build on RS6000 complete - `date`

 

.DEFAULT:

       @echo defaulting on "$@"  - don't know how to build it.

 

 


FILE:MAKEFILE.BIN

############################################################################

# Makefile for binopc and binops client/server DCE application program

#

# Author:   G.K. Springer at U of MO - Columbia

# Date:     Modified code created on 06/25/91 at MU.

# Node:     condor.cs.missouri.edu

# Place:    Computer Science Department, University of Missouri- Columbia

#

# Essentials to build the code on all platforms.  This is a dependant make

# file of the Binopdemo application makefile.

#

# Update Log:

#   9/08/93 - Changes to build code for a DCE system

#  04/22/95 - JimR: Changes for WIN32 compatibility

#

############################################################################

 

!IFDEF WIN32

 

!IFDEF DEBUG

LINK = link /DEBUG $(LINKFLGS)

!ELSE

LINK = link $(LINKFLGS)

!ENDIF

 

!IFDEF WIN32RAW

OBJC   = binop1_c.obj makepass.obj binopc.obj

!ELSE

OBJC   = binop1_cstub.obj makepass.obj binopc.obj

!ENDIF

OBJS   = binop1_sstub.obj binop1.obj binops.obj

OBJD   = binop1_cstub.obj makepass.obj binopdem.obj

OBJHLP = binop1_cstub.obj binophlp.obj

OBJST  = binop1_cstub.obj binopst.obj binop1_sstub.obj

SRVINC  = $(TSRC)\..\include\srvbase.h $(TSRC)\..\include\srvcln.h \

          $(TSRC)\musrv.h $(TSRC)\binopnms.h

 

 

#################################################################

# Default - build all of the code (binopc and binops)

#################################################################

#ALL:  $(T1)\binops.exe $(T1)\binopc.exe $(T1)\binopst.exe \

#        $(T1)\binophlp.exe $(T1)\binopdem.exe

 

# We can only build the client without the DCE extensions

!IFDEF WIN32RAW

ALL:   $(T1)\binopc.exe

!ELSE

ALL:   $(T1)\binopc.exe $(T1)\binopdem.exe $(T1)\binophlp.exe \

              $(T1)\binopst.exe $(T1)\binops.exe

!ENDIF

 

#################################################################

# Make the Server side of the process

#################################################################

#$(T1)\libmuns.a:

#$(T1)\libmutl.a:

#$(T1)\binops.exe:   $(OBJS) $(T1)\libmuns.a $(T1)\libmutl.a

$(T1)\binops.exe:    $(OBJS) $(T1)\muns.lib $(T1)\mutl.lib

       $(LINK) $(LIBS) $(LIB2) $(T1)\muns.lib $(T1)\mutl.lib /OUT:$(T1)\binops.exe $(OBJS)

#      $(CC) -o $(T1)\binops $(OBJS) -L$(T1) -lmutl $(LIBS) $(LIB2)

#      chmod 700 $(T1)\binops

#      chmod u+s $(T1)\binops

binops.obj:   binop1.h $(SRVINC) $(TSRC)\binops.c

       $(CC) $(CFLAGS) $(TSRC)\binops.c

binop1.obj:   binop1.h $(TSRC)\binop1.c

       $(CC) $(CFLAGS) $(TSRC)\binop1.c

#binop1_sstub.obj:   binop1.h binop1_sstub.c

#      @echo

#      @echo Make the server program

#      $(CC) $(CFLAGS) binop1_sstub.c

 

#################################################################

# Make the Client side of the application

#################################################################

!IFDEF WIN32RAW

$(T1)\binopc.exe:    $(OBJC)

       $(LINK) $(LIBS) $(LIB2) /OUT:$(T1)\binopc.exe $(OBJC)

!ELSE

$(T1)\binopc.exe:    $(OBJC) $(T1)\muns.lib

       $(LINK) $(LIBS) $(LIB2) $(T1)\muns.lib /OUT:$(T1)\binopc.exe $(OBJC)

!ENDIF

#      chmod 755 $(T1)\binopc

binopc.obj:   binop1.h $(TSRC)\binopc.c

       $(CC) $(CFLAGS) $(TSRC)\binopc.c

!IFDEF WIN32RAW

binop1_c.obj: binop1.h binop1_c.c

       @echo

       @echo Make the client program

       $(CC) $(CFLAGS) binop1_c.c

!ENDIF

 

#################################################################

# Make the BINOPDEMO Program

#################################################################

$(T1)\binopdem.exe:  $(OBJD) $(T1)\muns.lib

       $(LINK) $(LIBS) $(LIB2) $(T1)\muns.lib /OUT:$(T1)\binopdem.exe $(OBJD)

#      chmod 755 $(T1)\binopdem

binopdem.obj: binop1.h $(TSRC)\binopnms.h $(TSRC)\binopdem.c

       @echo

       @echo Make the demonstration program

       $(CC) $(CFLAGS) $(TSRC)\binopdem.c

 

#################################################################

# Make the BINOPST Program

#################################################################

$(T1)\binopst.exe:   $(OBJST) $(T1)\muns.lib $(T1)\mutl.lib

       $(LINK) $(LIBS) $(LIB2) $(T1)\muns.lib $(T1)\mutl.lib /OUT:$(T1)\binopst.exe $(OBJST)

#      $(CC) -o $(T1)\binopst $(OBJST) $(LIBS) $(LIB2)

#      chmod 755 $(T1)\binopst

binopst.obj:  binop1.h $(TSRC)\binopnms.h $(TSRC)\binopst.c

       @echo

       @echo Make the binop statistics program

       $(CC) $(CFLAGS) $(TSRC)\binopst.c

 

#################################################################

# Make the BINOPHLP Program

#################################################################

$(T1)\binophlp.exe:  $(OBJHLP) $(T1)\muns.lib

       $(LINK) $(LIBS) $(LIB2) $(T1)\muns.lib /OUT:$(T1)\binophlp.exe $(OBJHLP)

#      $(CC) -o $(T1)\binophlp $(OBJHLP) $(LIBS) $(LIB2)

#      chmod 755 $(T1)\binophlp

binophlp.obj: binop1.h $(TSRC)\binophlp.c

       @echo

       @echo Make the binop demonstration help program

       $(CC) $(CFLAGS) $(TSRC)\binophlp.c

 

#################################################################

# Make the Utility Code for Application

#################################################################

makepass.obj: binop1.h $(TSRC)\makepass.c

       $(CC) $(CFLAGS) $(TSRC)\makepass.c

#makepass.obj:       binop1.h $(TSRC)\makepass.cpp

#      $(CC) $(CFLAGS) $(TSRC)\makepass.cpp

 

 

 

#################################################################

# Call IDL compiler to build DCE stubs from idl definition

#################################################################

$(TSRC)\binop1.idl:

!IFDEF WIN32RAW

binop1_c.obj binop1_s.obj binop1.h:      $(TSRC)\binop1.idl

!ELSE

binop1_cstub.obj binop1_sstub.obj binop1.h:     $(TSRC)\binop1.idl

!ENDIF

       @echo

       @echo Create DCE stub code for the client and server

       $(IDL) $(IDLFLAGS) $(TSRC)\binop1.idl

 

#################################################################

# Cleanup files after build, including possibly the code modules

#################################################################

clean:

       @echo

       @echo Cleanup the binop directory

#      - rm -f binop*.obj makepass.obj binop1*.c binop1.h

#      - rm -i $(T1)\binops $(T1)\binopc $(T1)\binopdem $(T1)\binopst \

#        $(T1)\binophlp

 

 

!ELSE

 

 

 

OBJC   = binop1_cstub.o makepass.o binopc.o

OBJS   = binop1_sstub.o binop1.o binops.o

OBJD   = binop1_cstub.o makepass.o binopdemo.o

OBJHLP = binop1_cstub.o binophlp.o

OBJST  = binop1_cstub.o binopst.o

SRVINC  = $(TSRC)/../include/srvbase.h $(TSRC)/../include/srvcln.h \

          $(TSRC)/musrv.h $(TSRC)/binopnms.h

 

 

#################################################################

# Default - build all of the code (binopc and binops)

#################################################################

ALL:   $(T1)/binops $(T1)/binopc $(T1)/binopst \

        $(T1)/binophlp $(T1)/binopdemo

 

#################################################################

# Make the Server side of the process

#################################################################

$(T1)/libmuns.a:

$(T1)/libmutl.a:

$(T1)/binops: $(OBJS) $(T1)/libmuns.a $(T1)/libmutl.a

       $(CC) -o $(T1)/binops $(OBJS) -L$(T1) -lmutl $(LIBS) $(LIB2)

       chmod 700 $(T1)/binops

       chmod u+s $(T1)/binops

binops.o:     binop1.h $(SRVINC) $(TSRC)/binops.c

       $(CC) $(CFLAGS) $(TSRC)/binops.c

binop1.o:     binop1.h $(TSRC)/binop1.c

       $(CC) $(CFLAGS) $(TSRC)/binop1.c

binop1_sstub.o:      binop1.h binop1_sstub.c

       @echo

       @echo Make the server program

       $(CC) $(CFLAGS) binop1_sstub.c

 

#################################################################

# Make the Client side of the application

#################################################################

$(T1)/binopc: $(OBJC) $(T1)/libmuns.a

       $(CC) -o $(T1)/binopc $(OBJC) $(LIBS) $(LIB2)

       chmod 755 $(T1)/binopc

binopc.o:     binop1.h $(TSRC)/binopc.c

       $(CC) $(CFLAGS) $(TSRC)/binopc.c

binop1_cstub.o:      binop1.h binop1_cstub.c

       @echo

       @echo Make the client program

       $(CC) $(CFLAGS) binop1_cstub.c

 

#################################################################

# Make the BINOPDEMO Program

#################################################################

$(T1)/binopdemo:     $(OBJD) $(T1)/libmuns.a

       $(CC) -o $(T1)/binopdemo $(OBJD) $(LIBS) $(LIB2)

       chmod 755 $(T1)/binopdemo

binopdemo.o:  binop1.h $(TSRC)/binopnms.h $(TSRC)/binopdemo.c

       @echo

       @echo Make the demonstration program

       $(CC) $(CFLAGS) $(TSRC)/binopdemo.c

 

#################################################################

# Make the BINOPST Program

#################################################################

$(T1)/binopst:       $(OBJST) $(T1)/libmuns.a $(T1)/libmutl.a

       $(CC) -o $(T1)/binopst $(OBJST) $(LIBS) $(LIB2)

       chmod 755 $(T1)/binopst

binopst.o:    binop1.h $(TSRC)/binopnms.h $(TSRC)/binopst.c

       @echo

       @echo Make the binop statistics program

       $(CC) $(CFLAGS) $(TSRC)/binopst.c

 

#################################################################

# Make the BINOPHLP Program

#################################################################

$(T1)/binophlp:      $(OBJHLP) $(T1)/libmuns.a

       $(CC) -o $(T1)/binophlp $(OBJHLP) $(LIBS) $(LIB2)

       chmod 755 $(T1)/binophlp

binophlp.o:   binop1.h $(TSRC)/binophlp.c

       @echo

       @echo Make the binop demonstration help program

       $(CC) $(CFLAGS) $(TSRC)/binophlp.c

 

#################################################################

# Make the Utility Code for Application

#################################################################

makepass.o:   binop1.h $(TSRC)/makepass.c

       $(CC) $(CFLAGS) $(TSRC)/makepass.c

 

 

#################################################################

# Call IDL compiler to build DCE stubs from idl definition

#################################################################

$(TSRC)/binop1.idl:

binop1_cstub.c binop1_sstub.c binop1.h:  $(TSRC)/binop1.idl

       @echo

       @echo Create DCE stub code for the client and server

       $(IDL) $(IDLFLAGS) $(TSRC)/binop1.idl

 

#################################################################

# Cleanup files after build, including possibly the code modules

#################################################################

clean:

       @echo

       @echo Cleanup the binop directory

       - rm -f binop*.o makepass.o binop1*stub.c binop1.h

       - rm -i $(T1)/binops $(T1)/binopc $(T1)/binopdemo $(T1)/binopst \

         $(T1)/binophlp

!ENDIF

 

 


FILE:MAKEPASS.C

/*************************************************************************

 * DCE Function MAKEPASS.C - Function to make RPC calls to a Binop Server

 *

 * Author:   G.K. Springer

 * Date:     October 1993

 * Node:     condor.cs.missouri.edu

 * Location: Computer Science Department, University of Missouri-Columbia

 *

 * Purpose:  Demonstrate DCE Application Program

 *

 * Function: Implement an addition and subtraction RPC service.

 *

 * Syntax:   This function implements the actual RPC calls to the Server

 *              makepass(rh, num_passes)

 *         where:

 *            rh          - is a partially bound comm handle to server

 *            num_passes  - indicates how many loops of requests to perform

 *

 * Change Log:

 *  09/93 - GKS - Fixup for DCE implementation

 *************************************************************************/

 

/*

 * Standard C Include files

 */

#include <stdio.h>

 

#ifdef WIN32

#include <time.h>

#else

#include <sys/time.h>

#endif

 

#ifndef       WIN32RAW

#include <pthread.h>

 

/* Include DCE Definitions */

#include <dce/rpc.h>  /* DCE RPC definitions */

#include <dce/rpcexc.h>  /* DCE RPC exceptions */

#include <dce/dce_error.h>  /* DCE error definitions */

#else         /* WIN32 RAW */

#include <rpc.h>

#include "dceport.h"

#endif /* WIN32 RAW */

 

#include "binop1.h"  /* NIDL generated Interface definitions */

 

#define CALLS_PER_PASS 50

 

 

/***********************************************************************

 * makepass() - Send RPC requests to one of the requested servers

 *

 * Parameters:

 *    handle_t  rh;     -  Communication Handle

 *    int       passes; -  Number of passes to run

 ***********************************************************************/

makepass(handle_t rh, int passes)

{

   int          k;      /* Temp counter for passes run */

   int          i;      /* Temp variables */

   idl_long_int n;      /* return result from  RPC call */

   unsigned32   st;     /* Return status from RPC calls */

   int          start_time, stop_time;  /* Timing variables */

 

/* Start of processing */

   printf("\nStart Requests to: ");

   rpc_ep_resolve_binding(rh, binop_v1_0_c_ifspec, &st);

   rpc_mgmt_set_com_timeout(rh, rpc_c_binding_min_timeout, &st);

 

       #ifndef WIN32RAW

   st=p_handle(rh);

       #endif

 

   printf("\n");

 

/***********************************************************************

 * Loop for the requested number of passes to Server RPC Functions

 ***********************************************************************/

#ifndef WIN32RAW

TRY {

#endif

 for (k = 1; k <= passes; k++) {

   start_time = time(NULL);  /* Get TOD at start of a pass */

 /*

  * Call addition service the required number of times

  */

   for (i = 1; i <= CALLS_PER_PASS; i++) {

      binop_add(rh, i, i, &n);  /* Call RPC ADD service on Server */

      printf("%3d ",n);  /* Print result returned */

      /* add a newline every 10 results returned */

      if ((i%10 == 0) && (i != CALLS_PER_PASS)) printf("\n");

      fflush(stdout);

      if (n != i+i)  /* Check that we got correct result */

         printf("\n %ld + %ld is NOT %ld\n", i, i, n);

      }  /* end for i - addition loop */

      printf("  *** end of addition ***\n");

 

 /*

  * Call subtraction service the required number of times

  */

   for (i = 1; i <= CALLS_PER_PASS; i++) {

   /*

    *   Check to see if an error occurred - returns here on an error.

    */

      binop_sub(rh, CALLS_PER_PASS+1 , i, &n); /* Call RPC SUB service */

      printf("%3d ",n);  /* Print result returned */

      /* add a newline every 10 results returned */

      if ((i%10 == 0) && (i != CALLS_PER_PASS)) printf("\n");

      fflush(stdout);

      if (n != CALLS_PER_PASS+1-i)  /* Check that we got correct result */

         printf("\n %ld - %ld is NOT %ld\n", CALLS_PER_PASS, i, n);

      }  /* end for i - subtraction loop */

      printf("  *** end of subtraction ***\n");

 

/*

 * Calculate average time to process a call

 */

   stop_time = time(NULL);  /* Get TOD and end of pass */

   printf("***** pass %3d; real/call: %2d ms\n",

           k, ((stop_time - start_time) * 1000) / (2*CALLS_PER_PASS));

   }  /* end for k - number of passes */

#ifndef       WIN32RAW

}

 

CATCH (rpc_x_comm_failure) {

   printf("\t***ERROR*** Communication failure during RPC call\n");

   }

 

CATCH_ALL {

   printf("\t***ERROR*** Error occurred during RPC call\n");

   }

 

ENDTRY;

#endif /* WIN32RAW */

return;

}  /* end makepass() */

 

 


FILE:MUSRV.H

/*************************************************************************

 * Include File:  musrv.h - Include common definitions used by a server

 *

 * Author:   G.K. Springer

 * Date:     February 1994

 * Node:     condor.cs.missouri.edu

 * Place:    Computer Science Department, University of Missouri-Columbia

 *

 * Purpose:  Define common routines and constants used by an application

 *           server using DCE.

 *

 * Function: Define symbolic contants and include files used by a server

 *

 * Syntax:   This is an include file called from the server source code

 *

 * Change Log:

 *  02/95 GKS - Added code for generating unique logging transaction ids

 *

 *************************************************************************/

 

#ifndef MUSRV

#define MUSRV 1

 

/* Define Server Principal and interface routines to identify and refresh

 * the server's DCE security credentials

 */

/* JimR Note - PROBLEM! - It seems that this should be taken from the */

/* login name of whomever is currently signed on when the server is   */

/* started.  Hard-coding here seems like a bummer.                    */

static char     *principal = "springer";

 

/* Identify Common Utility Functions for Server */

void tmsg();     /* Print time-stamped messages */

char *dcemsg();  /* DCE error msg lookup routine */

unsigned32 p_handle(rpc_binding_handle_t); /* print a binding handle as text */

 

/* Bring in Application Specific Server Include Files */

#include <binop1.h>  /* DCE IDL generated header file for the server */

#include <binopnms.h>      /* DCE NS names for this server */

#include <daemon.h>     /* to make the server into a daemon */

#include <dceconfig.h>  /* names needed by server for log info */