The helloc.c source file contains a directive to include the MIDL-generated header file, hello.h. Within hello.h are directives to include rpc.h and rpcndr.h, which contain the definitions for the RPC runtime routines and data types that our client and server applications use.
Because the client is managing its connection to the server, the client application calls run-time functions to establish a handle to the server and to release this handle after the remote procedure calls are complete. The function RpcStringBindingCompose combines the components of the binding handle into a string representation of that handle and allocates memory for the string binding. The function RpcBindingFromStringBinding creates a server binding handle, hello_IfHandle, for the client application from that string representation.
In the call to RpcStringBindingCompose, we have not specified the UUID because we have just one implementation of the interface "hello". We also have not specified a network address because we want the default, which is the local host machine. The protocol sequence is a character string that represents the underlying network transport and the endpoint is a name that is specific to the protocol sequence. We are using named pipes (a native Windows NT protocol) for our network transport, so the protocol sequence is "ncacn_np" and we have named our endpoint "\pipe\hello".
The actual remote procedure calls, HelloProc and Shutdown, take place within the RPC exception handler — a set of macros that let you control exceptions that occur outside the application code. If the RPC runtime module reports an exception, control passes to the RpcExcept block, which is where you would insert code to do any needed cleanup and then exit gracefully. In our example, we need only inform the user that an exception ocurred.
After the remote procedure calls are completed the client first calls RpcStringFree to free the memory that was allocated for the string binding, and then calls RpcBindingFree to release the handle.
/* file: helloc.c */
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "hello.h"
void main()
{
RPC_STATUS status;
unsigned char * pszUuid = NULL;
unsigned char * pszProtocolSequence = "ncacn_np";
unsigned char * pszNetworkAddress = NULL;
unsigned char * pszEndpoint = "\\pipe\\hello";
unsigned char * pszOptions = NULL;
unsigned char * pszStringBinding = NULL;
unsigned char * pszString = "hello, world";
unsigned long ulCode;
status = RpcStringBindingCompose(pszUuid,
pszProtocolSequence,
pszNetworkAddress,
pszEndpoint,
pszOptions,
&pszStringBinding);
if (status) {
exit(status);
}
status = RpcBindingFromStringBinding(pszStringBinding,
&hello_IfHandle);
if (status) {
exit(status);
}
RpcTryExcept {
HelloProc(pszString);
Shutdown();
}
RpcExcept(1) {
ulCode = RpcExceptionCode();
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
}
RpcEndExcept
status = RpcStringFree(&pszStringBinding);
if (status) {
exit(status);
}
status = RpcBindingFree(&hello_IfHandle);
if (status) {
exit(status);
}
exit(0);
} // end main()