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

#include "factl.h"    // header file generated by MIDL compiler
#include "globals.h"   // contains defines used by FACTL program

              
//
//  FUNCTION: factl(unsigned char *pszN, unsigned chare **pszResult)
//
//  PURPOSE: Computes factorial function of integer pointed by pszN.
//
//  PARAMETERS:
//    
//    pszN        - ptr to ascii string contain integer to compute factorial
//    ppszResult  - Double indirection pointer to place factorial computation
//                  result
//  
//  RETURN VALUE:
// 
//    Returns 
//      -1   If function could not compute factorial of pszN 
//       1   Factorial computation was successful. Factorial funtion results 
//           are pointed by ppszResult.
//
//  COMMENTS: This is a very simple factorial routine for demonstration 
//            purposes only. 
//      

short factl(unsigned char *pszN, unsigned char **ppszResult)
{
    LONG N, tmp;


    if ((pszN != NULL) && ((N = atol(pszN)) >= 0) && (N <= 12)) 
                                                // 12! = max LONG supported
    {
        printf("\nA client requested computation of factorial of %d.\n"
               "\nComputing...\n",N);
    }
    else
    {
    return(-1);
    }

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

    *ppszResult = MIDL_user_allocate(BUF_SIZE);

    for (tmp = N; --tmp > 1;) 
    {
        N = N * tmp;

    }

    ltoa(N, *ppszResult, 10);

    printf("\nFactorial computation is finished. The result is %s.\n\n", *ppszResult);

    return (1);
}



//
//  FUNCTION: Shutdown(void)
//
//  PURPOSE: Shuts down and unregisters RPC server.
//
//  PARAMETERS:
//    
//    none.
//  
//  RETURN VALUE:
// 
//    none.
//
//  COMMENTS:
//


void Shutdown(void)
{
    RPC_STATUS status;
    RPC_BINDING_VECTOR * pBindingVector;                                                                
                                        
                                                                
    // 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) 
    {
        exit(status);
    }                                                                


    // Remove server-address information from the local
    // endpoint-map database

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcEpUnregister()...\n");
#endif
    
    status = RpcEpUnregister(factl_ServerIfHandle,
                             pBindingVector,
                             NULL);              
#if defined(FACTL_DEBUG)
    printf("\nDEBUG: RpcEpUnregister() returned 0x%x\n", status);
#endif

    if (status) {
    	exit(status);
    }
     
     
    // 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) 
    {
        exit(status);
    }
    
        
    // Removes the binding handles for an interface 
    // from an entry in the name-service database.

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcNsBindingUnexport()...\n");
#endif
    
    status = RpcNsBindingUnexport(RPC_C_NS_SYNTAX_DEFAULT, // entry name syntax
                                  "/.:/Autohandle_factl",  // entry name
                                  factl_ServerIfHandle,    // interface name
                                  NULL);                   // no UUID vector 
    
#if defined(FACTL_DEBUG)
    printf("\nDEBUG: RpcNsBindingUnexport() returned 0x%x\n", status);
#endif

    if (status) {
    exit(status);
    }

    
    // Unregister interface from the RPC runtime database.

#if defined(FACTL_DEBUG)
    printf("\nDEBUG: Calling RpcServerUnregisterIf()...\n");
#endif
                                                          
    status = RpcServerUnregisterIf(NULL, NULL, FALSE);

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

    if (status) {
    exit(status);
    }

                                                                    
    // Tell server to stop listening for remote procedure calls.

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

    status = RpcMgmtStopServerListening(NULL);

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

    if (status) {
    exit(status);
    }
                                                                
} /* end of Shutdown */

