O aplicativo cliente

O exemplo a seguir é do aplicativo 'Olá, Mundo' no diretório RPC\Hello do SDK (Platform Software Development Kit). O arquivo de origem Helloc.c contém uma diretiva para incluir o arquivo de cabeçalho gerado por MIDL, Hello.h. No Hello.h há diretivas para incluir Rpc.h e rpcndr.h, que contêm as definições para as rotinas de tempo de execução RPC, HelloProc e Shutdown e tipos de dados que os aplicativos cliente e servidor usam. O compilador MIDL deve ser usado com o exemplo abaixo.

Como o cliente está gerenciando sua conexão com o servidor, o aplicativo cliente chama funções em tempo de execução para estabelecer um identificador para o servidor e liberar esse identificador após a conclusão das chamadas de procedimento remoto. A função RpcStringBindingCompose combina os componentes do identificador de associação em uma representação de cadeia de caracteres desse identificador e aloca memória para a associação de cadeia de caracteres. A função RpcBindingFromStringBinding cria um identificador de associação de servidor, hello_ClientIfHandle, para o aplicativo cliente dessa representação de cadeia de caracteres.

Na chamada para RpcStringBindingCompose, os parâmetros não especificam a UUID porque este tutorial pressupõe que há apenas uma implementação da interface "hello". Além disso, a chamada não especifica um endereço de rede porque o aplicativo usará o padrão, que é o computador host local. A sequência de protocolo é uma cadeia de caracteres que representa o transporte de rede subjacente. O ponto de extremidade é um nome específico para a sequência de protocolo. Este exemplo usa pipes nomeados para seu transporte de rede, portanto, a sequência de protocolo é "ncacn_np". O nome do ponto de extremidade é "\pipe\hello".

As chamadas de procedimento remoto reais, HelloProc e Shutdown, ocorrem dentro do manipulador de exceção RPC— um conjunto de macros que permitem controlar exceções que ocorrem fora do código do aplicativo. Se o módulo de tempo de execução RPC relatar uma exceção, o controle passará para o bloco RpcExcept . É aqui que você insere o código para fazer qualquer limpeza necessária e sair normalmente. Este programa de exemplo simplesmente informa ao usuário que ocorreu uma exceção. Se você não quiser usar exceções, poderá usar os atributos ACF comm_status e fault_status para relatar erros.

Depois que as chamadas de procedimento remoto forem concluídas, o cliente primeiro chamará RpcStringFree para liberar a memória alocada para a associação de cadeia de caracteres. Observe que, depois que o identificador de associação for criado, um programa cliente poderá liberar uma associação de cadeia de caracteres a qualquer momento. Em seguida, o cliente chama RpcBindingFree para liberar o identificador.

/* file: helloc.c */
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "hello.h" 
#include <windows.h>

void main()
{
    RPC_STATUS status;
    unsigned char * pszUuid             = NULL;
    unsigned char * pszProtocolSequence = "ncacn_np";
    unsigned char * pszNetworkAddress   = NULL;
    unsigned char * pszEndpoint         = "\\pipe\\hello";
    unsigned char * pszOptions          = NULL;
    unsigned char * pszStringBinding    = NULL;
    unsigned char * pszString           = "hello, world";
    unsigned long ulCode;
 
    status = RpcStringBindingCompose(pszUuid,
                                     pszProtocolSequence,
                                     pszNetworkAddress,
                                     pszEndpoint,
                                     pszOptions,
                                     &pszStringBinding);
    if (status) exit(status);

    status = RpcBindingFromStringBinding(pszStringBinding, &hello_ClientIfHandle);
 
    if (status) exit(status);
 
    RpcTryExcept  
    {
        HelloProc(pszString);
        Shutdown();
    }
    RpcExcept(1) 
    {
        ulCode = RpcExceptionCode();
        printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
    }
    RpcEndExcept
 
    status = RpcStringFree(&pszStringBinding); 
 
    if (status) exit(status);
 
    status = RpcBindingFree(&hello_IfHandle);
 
    if (status) exit(status);

    exit(0);
}

/******************************************************/
/*         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);
}