/****************************************************************************
                   Microsoft RPC Version 2.0
           Copyright Microsoft Corp. 1992, 1993, 1994
                       Doctor Example

    FILE:       doctorc.c
    
    USAGE:      doctorc  -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 version of the distributed application prints
                strings from the Doctor server.  Doctor is an Eliza-like
                personal therapist program that works by simple 
                pattern-matching.

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

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

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

#define GREETING \
"The doctor is in.\n\
I am at your service; just tell me anything that troubles\n\
or concerns you. Please end your sentences with a period,\n\
a question mark, or an exclamation point, and then press\n\
the RETURN or ENTER key.  When you are ready to quit our\n\
session, just enter \"bye\" and press RETURN or ENTER.\n\n\
What is your name? >"

#define FAREWELL \
"I hope I have been of some service to you.\n\
Let's get together again some time.\n\n"


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;                 // returned by RPC API function
    unsigned char pszName[STRSIZE];    // patient name
    unsigned char achIn[STRSIZE];      // patient input

    unsigned char * pszUuid             = NULL;
    unsigned char * pszProtocolSequence = "ncacn_np";
    unsigned char * pszNetworkAddress   = NULL;
    unsigned char * pszEndpoint         = "\\pipe\\doctor";
    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]);
    }

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

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

    /* RPC is now initialized.  Call remote procedures as if        */
    /* they were local procedures.                                  */

    /* The doctor program consists of patient statements and doctor */
    /* responses.  The patient string is transmitted to the server, */
    /* and all processing is performed on the server.               */
    
    printf("%s", GREETING);
    gets(pszName);
    printf("\n%s>", pszName);

    while (gets(achIn)) {
        if (strncmp(achIn, "bye", 3) == 0)  // end of session?
            break;
        RpcTryExcept {
            Analyze(&achIn[0]);
        }
        RpcExcept(1) {
            printf("Runtime reported exception %ld\n", RpcExceptionCode() );
	    break;
        }
        RpcEndExcept

        printf("%s%s>", achIn, pszName);    // no, continue
    }

    RpcTryExcept {
        Shutdown();                             // yes, shutdown the server
    }
    RpcExcept(1) {
        printf("Runtime reported exception %ld\n", RpcExceptionCode() );
    }
    RpcEndExcept

    /*  The calls to the remote procedure are complete.  */
    /*  Free the binding handle.                         */
    status = RpcBindingFree(&doctor_IfHandle);  // remote calls done; unbind
    if (status) {
       printf("RpcBindingFree returned 0x%x\n", status);
       exit(status);
    }

    printf("%s", FAREWELL);

    exit(0);

}  // end main()


/*********************************************************************/
/*                 MIDL allocate and free                            */
/*********************************************************************/

void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
{
    return(malloc(len));
}

void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
    free(ptr);
}

/* end file doctorc.c */
