// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (C) 1993, 1994  Microsoft Corporation. All rights
// Reserved.
//
//  MODULE:  factls.c
//
//  PURPOSE: RPC factorial program that demonstrates the use of the following:
//
//           a) Server registration of RPC procedures on all available
//              protocol sequences.
//           b) Auto handles. There is not need to specify server names
//              or to write RPC client code to deal with binding and 
//              handles.The RPC stubs defines the handle and manages the
//              binding.
//           c) RPC Server/Client dynamic allocation of memory. The use
//              of double indirection reference pointers to pass arbitrary
//              amounts and types of data is shown.
//
//  FUNCTIONS:             
//    main                  - Main server procedure
//    MIDL_user_allocate    - Allocates memory on the server address space
//    MIDL_user_free        - Deallocates memory on the server address space
//
//  COMMENTS:
//


#include <stdio.h>
#include <stdlib.h>

#include "factl.h"
#include "globals.h"


main(int argc, char *argv[])

{

    RPC_STATUS status;
    RPC_BINDING_VECTOR * pBindingVector;
    unsigned char * pszSecurityDescriptor = NULL;


    printf("\nInitializing Factorial Server. Please wait a few minutes...\n");


    // Use all protocol sequences to receive requests from clients.    

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcServerUseAllProtseqs()...\n");
#endif
    
    status = RpcServerUseAllProtseqs(RPC_C_PROTSEQ_MAX_REQS_DEFAULT, 
                                     pszSecurityDescriptor);

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: RpcServerUseAllProtseqs() returned 0x%x\n",status);
#endif

    if (status) 
    {
        Shutdown();
    }


    // Obtain a vector containing all of the server's binding handles.

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcServerInqBindings()...\n");
#endif

    status = RpcServerInqBindings(&pBindingVector);

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: RpcServerInqBindings() returned 0x%x\n", status);
#endif

    if (status) 
    {                
        Shutdown();
    }

    
    // register the binding handles with the endpoint-mapping service

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcEpRegister()...\n");
#endif

    status = RpcEpRegister(factl_ServerIfHandle,
                           pBindingVector,
                           NULL,
                           NULL);

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: RpcEpRegister() returned 0x%x\n", status);
#endif

    if (status) 
    {           
        Shutdown();
    }


    // Place the binding handles in the name-service database for 
    // access by any client.

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcNsBindingExport()...\n");
#endif

    status = RpcNsBindingExport(
            RPC_C_NS_SYNTAX_DEFAULT,    /* entry name syntax */
            "/.:/Autohandle_factl",    /* entry name */
            factl_ServerIfHandle,
            pBindingVector,
            NULL);  /* UUID vector */

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: RpcNsBindingExport() returned 0x%x\n", status);
#endif

    if (status) 
    {
        Shutdown();
    }


    // Free the vector of server binding handles.

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcBindingVectorFree()...\n");
#endif

    status = RpcBindingVectorFree(&pBindingVector);

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: RpcBindingVectorFree() returned 0x%x\n", status);
#endif

    if (status) 
    {
        Shutdown();      
    }


    // Register the interfaces offered by the server with the RPC 
    // run-time library.

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcServerRegisterIf()...\n");
#endif

    status = RpcServerRegisterIf(factl_ServerIfHandle,
                                 NULL,
                                 NULL);

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: RpcServerRegisterIf() returned 0x%x\n", status);
#endif

    if (status) 
    {
        Shutdown();
    }


    // RpcServerListen to begin receiving remote procedure call requests.

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcServerListen()...\n");
#endif

    printf("\nServer ready to accept client request...\n");

    status =  RpcServerListen(1,         // minimun # of calls 
                              RPC_C_LISTEN_MAX_CALLS_DEFAULT,  // max calls
                              0);        // wait until all calls have completed

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: RpcServerListen() returned 0x%x\n", status);
#endif

    if (status) 
    {
        Shutdown();        
    }
    
    printf("\nServer FACTL program terminated sucessfully...Bye now...\n");

    return(0);

} /* end of main */


//
//  FUNCTION: MIDL_user_allocate(size_t len)
//
//  PURPOSE: Server stub calls this function to allocate memory when
//           remote procedure has to pass parameters to server application.
//
//  PARAMETERS:
//    
//    len     - number of bytes to allocate
//  
//  RETURN VALUE:
// 
//    Returns pointer to allocated memory
//
//  COMMENTS:
//


void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len)
{

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Memory is being allocated for the client on"
           " the server process space.\n");
#endif

    return(malloc(len));

}


//
//  FUNCTION: MIDL_user_free(size_t len)
//
//  PURPOSE: Server stub calls this function to free memory
//           allocated using MIDL_user_allocate().
//
//  PARAMETERS:
//    
//    ptr     - pointer to memory to deallocate.
//  
//  RETURN VALUE:
// 
//    None.
//
//  COMMENTS:
//

void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
{

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Memory is being deallocated for the client on"
           " the server process space.\n");
#endif

    free(ptr);

}
