RPCSSMC.C

/**************************************************************************** 
Microsoft RPC Version 2.0
Copyright Microsoft Corp. 1992, 1993, 1994- 1996
rpcssm Example

FILE: rpcssmc.c

USAGE: rpcssmc -n network_address
-p protocol_sequence
-e endpoint
-o options

PURPOSE: Client side of RPC distributed application

FUNCTIONS: main() - binds to server and calls remote procedure

COMMENTS: This distributed application uses the rpcssm package.

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

#include <stdlib.h>
#include <stdio.h>
#include "rpcssm.h" // header file generated by MIDL compiler


#define PURPOSE \
"This Microsoft RPC Version 2.0 sample program demonstrates\n\
the use of the [context_handle] attribute. For more information\n\
about attributes and RPC API functions, see the RPC programming\n\
guide and reference.\n\n"

void AllocateSmList( PBOX * ppBox, short sListSize );
void AllocateList( PBOX * ppBox, short sListSize );
void InitList( PBOX pBox, long lStartValue );
void FreeList( PBOX pBox );
void PrintList( PBOX pBox );


void Usage(char * pszProgramName)
{
fprintf(stderr, "%s", PURPOSE);
fprintf(stderr, "Usage: %s\n", pszProgramName);
fprintf(stderr, " -p protocol_sequence\n");
fprintf(stderr, " -n network_address\n");
fprintf(stderr, " -e endpoint\n");
fprintf(stderr, " -o options\n");
exit(1);
}

void _CRTAPI1 main(int argc, char **argv)
{
RPC_STATUS status;
PBOX pBox = NULL;

unsigned char * pszUuid = NULL;
unsigned char * pszProtocolSequence = "ncacn_np";
unsigned char * pszNetworkAddress = NULL;
unsigned char * pszEndpoint = "\\pipe\\rpcssm";
unsigned char * pszOptions = NULL;
unsigned char * pszStringBinding = NULL;
int i;

/* allow the user to override settings with command line switches */
for (i = 1; i < argc; i++) {
if ((*argv[i] == '-') || (*argv[i] == '/')) {
switch (tolower(*(argv[i]+1))) {
case 'p': // protocol sequence
pszProtocolSequence = argv[++i];
break;
case 'n': // network address
pszNetworkAddress = argv[++i];
break;
case 'e':
pszEndpoint = argv[++i];
break;
case 'o':
pszOptions = argv[++i];
break;
case 'h':
case '?':
default:
Usage(argv[0]);
}
}
else
Usage(argv[0]);
}

RpcTryExcept {

/* Use a convenience function to concatenate the elements of */
/* the string binding into the proper sequence. */
status = RpcStringBindingCompose(pszUuid,
pszProtocolSequence,
pszNetworkAddress,
pszEndpoint,
pszOptions,
&pszStringBinding);
printf("RpcStringBindingCompose returned 0x%x\n", status);
printf("pszStringBinding = %s\n", pszStringBinding);
if (status) {
exit(status);
}

/* Set the binding handle that will be used to bind to the server. */
status = RpcBindingFromStringBinding(pszStringBinding,
&hStarter);
printf("RpcBindingFromStringBinding returned 0x%x\n", status);
if (status) {
exit(status);
}

/* Now a different case: a client stub is in an enabled environment */

status = RpcSmEnableAllocate();
printf("RpcSmEnableAllocate returned 0x%x\n", status);
if (status) {
exit(status);
}

pBox = NULL;
AllocateSmList( &pBox, 4 );
InitList( pBox, 0xabcd0000 );
PrintList( pBox );

printf("Calling the remote procedure InOutList\n");
InOutList( &pBox );
PrintList( pBox );

/* No need to free the memory allocated with RpcSmAllocate,
RpcSmDisableAllocate would free it.
*/

status = RpcSmDisableAllocate();
printf("RpcSmDisableAllocate returned 0x%x\n", status);
if (status) {
exit(status);
}

printf(" All nodes from this case freed by RpcSmDisableAllocate().\n" );
printf(" Client with memory environment done.\n\n" );

Shutdown();

/* Free the string binding */
status = RpcStringFree(&pszStringBinding);
printf("RpcStringFree returned 0x%x\n", status);
if (status) {
exit(status);
}

status = RpcBindingFree(&hStarter);
printf("RpcBindingFree returned 0x%x\n", status);
if (status) {
exit(status);
}
}
RpcExcept(1) {

#if defined(WIN32)
printf( "Unexpected exception: %ld\n", RpcExceptionCode() );
#else
printf( "Unexpected exception: %d\n", RpcExceptionCode() );
#endif
printf("Did you set a net address (like -n server_name etc.)?\n");
exit(1);
}
RpcEndExcept;

exit(0);

} // end main()


//=====================================================================
// List allocation/deallocation routines
//=====================================================================

void
AllocateSmList( PBOX * ppBox, short sListSize)
{
PBOX pBox, head;
int i = 0;

//.. Allocate a list of boxes, if needed (when *ppBox==NULL).

if ( *ppBox == NULL ) {

RPC_STATUS status;

head = 0;
for (i = 0; i < sListSize; i++)
{
pBox = (PBOX) RpcSmAllocate( sizeof(LBOX), &status);
if ( status != RPC_S_OK )
{
printf("AllocateList FAILED: not enough memory\n");
break;
}
pBox->next = head;
head = pBox;
}
*ppBox = head;
}
printf("%d nodes allocated.\n", i);
}

//=====================================================================
// Initialization and pprint routines
//=====================================================================

void InitList( PBOX pBox, long lStartValue )
{
int i = 0;

while( pBox ) {
pBox->data = lStartValue + ++i;
pBox = pBox->next;
}
printf("%d nodes inited.\n", i);
}

// --------------------------------------------------------------------

void
PrintList( PBOX pBox )
{
int i = 0;


while( pBox ) {

if ( (i % 4) != 0 )
printf(" data[%d]= %lx", i, pBox->data);
else
printf( "\n data[%d]= %lx", i, pBox->data);
pBox = pBox->next;
i++;
}
printf("\n" );
}


/* end rpcssmc.c */