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