/*************************************************************************
                    Copyright Microsoft Corp. 1992-1996
                        Remote Machine strout sample

  FILE      :   server.c

  USAGE     :   server  -p protocol_sequence
                        -e endpoint
                        
  PURPOSE   :   Server side of the RPC distributed application strout.

  COMMENTS  :   This application uses the implicit binding method.

*************************************************************************/
#include "strout.h"                 /* Generated by the midl compiler   */
#include "common.h"                 /* Common definitions in this file  */

/* Local Procedures */
void CleanUpServer(void);


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*  Procedure   :   void Usage(_TUCHAR *)                               */
/*  Desc        :   This procedure prints out an error message if the   */
/*                  command line arguments are wrong                    */
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void Usage(_TUCHAR * pszProgramName)
{
    _tprintf(TEXT("USAGE : %s [-option]\n"), pszProgramName);
    _tprintf(TEXT("Options : -p Protocol Sequence\n"));  
    _tprintf(TEXT("          -e Endpoint\n"));  
    exit(EXECUTION_OK);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* The server main program                                              */
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int main(int argc, char *argv[])
{
    int             nNumArgs,   /* The number of command line arguments */
                    nIdx;       /* Counter in loops                     */
    RPC_STATUS      nStatus;    /* Error status returned                */

    // Variabels used for selecting the protocol and the endpoint
    _TUCHAR *pszProtocolSequence    = PROTOCOL_SEQUENCE;
    _TUCHAR *pszEndpoint            = END_POINT;
    _TUCHAR *pszSecurity            = NULL;


/* Get a common handle on the command line arguments for both UNICODE   */
/* and ASCII                                                            */
#ifdef _UNICODE
    LPWSTR	*pArglist = CommandLineToArgvW(GetCommandLine(), &nNumArgs);
    if (NULL == pArglist)
    {
        _tprintf(TEXT("SERVER.C : CommandLineToArgW failed"));
        exit(EXECUTION_FAILED);
    }
#else
    char **pArglist = argv;
    nNumArgs = argc;
#endif

    /* Allow the user to override settings with commandline switches    */
    for (nIdx = 1; nIdx < nNumArgs; nIdx++) 
    {
        if((_tcscmp(pArglist[nIdx], TEXT("-p")) == 0) || 
           (_tcscmp(pArglist[nIdx], TEXT("-P")) == 0))
        {
            pszProtocolSequence = pArglist[++nIdx];
        }
        else if((_tcscmp(pArglist[nIdx], TEXT("-e")) == 0) || 
                (_tcscmp(pArglist[nIdx], TEXT("-e")) == 0))
        {
            pszEndpoint = pArglist[++nIdx];
        }
        else 
        {
            Usage(pArglist[0]);
        }
    }
            
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /* Register the interface with the RPC run-time library             */
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    _tprintf(TEXT("Registering the interface\n"));
    nStatus = RpcServerRegisterIf(
        strout_sample_v1_0_s_ifspec,    // Interface specification
        NULL,                           // UUID to ass. with MgrEnv arg.
        NULL);                          // Managers entry point vector.
    EXIT_IF_FAIL(nStatus, "RpcServerRegisterIf");


    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /* Select Protocal sequence : This sample uses namedpipes as the    */
    /* default protocol. The RpcServerUseProtseqEp function tells the   */
    /* RPC run-time library to use the specified protocol sequence      */
    /* combined with the specified endpoint for receiving remote        */
    /* procedure calls                                                  */
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    _tprintf(TEXT("Selecting the protocol sequence: \"%s\"\n"),
        pszProtocolSequence);
    nStatus = RpcServerUseProtseqEp(
        pszProtocolSequence,            // String with the protocol in
        RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // Max number of calls
        pszEndpoint,                    // Endpoint addres information
        pszSecurity);                   // Security
    EXIT_IF_FAIL(nStatus, "RpcServerUseProtseqsEp");

	
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /* Now start listening for remote procedure calls from the client   */
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    RpcTryExcept
    {
        _tprintf(TEXT("Listening for remote calls...\n"));
        nStatus = RpcServerListen(
            1,                              // The minimum number of calls
            RPC_C_LISTEN_MAX_CALLS_DEFAULT, // The maximum number of calls
            FALSE);                         // Cont. until expl. stopped
        EXIT_IF_FAIL(nStatus, "RpcServerListen");
    }
    RpcExcept(DO_EXCEPTION)
    {
        // Print out the exception code 
        _tprintf(TEXT("Run-time exception %u in %s at line %d\n"), 
                RpcExceptionCode(), TEXT(__FILE__), __LINE__);
        exit(EXECUTION_FAILED);
    }
    RpcEndExcept


    // If no exceptions occured, clean up the server and exit
    CleanUpServer();

    // Deallocate the memory used for the ARGLIST if using UNICODE
#ifdef _UNICODE
    if (NULL != pArglist)
        free(pArglist);
#endif

    return (EXECUTION_OK);
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* Procedure    : void CleanUpServer(RPC_BINDING_VECTOR);               */
/* Desc.        : This procedure will unregister the interface          */
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void CleanUpServer(void)
{
    RPC_STATUS nStatus;          // Error status returned from RPC calls 

    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /* Unregister the interface from the RPC run-time library           */
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    _tprintf(TEXT("Unregistering the Interface"));
    nStatus = RpcServerUnregisterIf(
        NULL, NULL, // Prevents server from receiving new remote calls
        FALSE);     // Wait until all the active calls are complete 
    EXIT_IF_FAIL(nStatus, "RpcServerUnRegisterIf");
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* Procedure    :   midl_user_allocate() and midl_user_free()           */
/* Desc.        :   These procedure are declared in the header file     */
/*                  generated by the midl compiler. These procedures    */
/*                  should be used for all memory allocation and        */
/*                  deallocation.                                       */
/*                  These procedures are also called by the stub code   */
/*                  to allocate and free memory.                        */
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void __RPC_FAR * __RPC_API midl_user_allocate(size_t nLen)
{
    return (malloc(nLen));
}

void __RPC_API midl_user_free(void __RPC_FAR * lpvPointer)
{
    if(NULL != lpvPointer)
        free (lpvPointer);
}

