/****************************************************************************
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 */