Partilhar via


Técnicas IDL para Melhor Interface e Design de Método

Considere o uso das seguintes técnicas específicas de IDL para melhorar a segurança e o desempenho ao desenvolver interfaces e métodos RPC que lidam com dados conformes e variantes. Os atributos mencionados neste tópico são os atributos IDL definidos em parâmetros de método que manipulam dados conformes (por exemplo, os atributos [size_is] e [max_is] ) ou variantes (por exemplo, os atributos [length_is] e [string].

Usando o atributo [range] com parâmetros de dados conformes

O atributo [range] instrui o tempo de execução RPC a executar a validação de tamanho adicional durante o processo de desempacotamento de dados. Especificamente, ele verifica se o tamanho fornecido dos dados passados como o parâmetro associado está dentro do intervalo especificado.

O atributo [range] não afeta o formato de fio.

Se o valor no fio estiver fora do intervalo permitido, o RPC lançará uma exceção RPC_X_INVALID_BOUND ou RPC_X_BAD_STUB_DATA. Isso fornece um nível adicional de validação de dados e pode ajudar a evitar erros comuns de segurança, como saturações de buffer. Da mesma forma, o uso de [range] pode melhorar o desempenho do aplicativo, uma vez que os dados conformes marcados com ele têm restrições claramente definidas disponíveis para consideração pelo serviço RPC.

Regras de gerenciamento de memória de stub do servidor RPC

É importante entender as regras de gerenciamento de memória de stub do servidor RPC ao criar os arquivos IDL para um aplicativo habilitado para RPC. Os aplicativos podem melhorar a utilização de recursos do servidor usando [intervalo] em conjunto com dados conformes, conforme indicado acima, bem como evitando deliberadamente a aplicação de atributos IDL de dados de comprimento variável, como [length_is] a dados conformes.

A aplicação de [length_is] a campos de estrutura de dados definidos em um arquivo IDL não é recomendada.

Práticas recomendadas para parâmetros de dados de comprimento variável

A seguir estão várias práticas recomendadas a serem consideradas ao definir os atributos IDL para estruturas de dados de tamanho variável, parâmetros de método e campos.

  • Use correlação precoce. Geralmente, é melhor definir o parâmetro de tamanho variável ou campo de tal forma que ocorra imediatamente após o tipo integral de controle.

    Por exemplo

    earlyCorr
    (
    [in, range(MIN_COUNT, MAX_COUNT)] long size, 
    [in,size_is(size)] char *pv
    );
    

    é melhor do que

    lateCorr
    (
    [in,size_is(size)] char *pv, 
    [in, range(MIN_COUNT, MAX_COUNT)] long size)
    );
    

    em que earlyCorr declara o parâmetro size imediatamente antes do parâmetro de dados de comprimento variável, e lateCorr declara o parâmetro size depois dele. O uso de correspondência precoce melhora o desempenho geral, especialmente nos casos em que o método é chamado com frequência.

  • Para parâmetros marcados com a tupla de atributo [out, size_is] e onde o comprimento dos dados é conhecido no lado do cliente ou onde o cliente tem um limite superior razoável, a definição do método deve ser semelhante à seguinte em termos de atribuição e sequência de parâmetros:

    outKnownSize
    (
    [in,range(MIN_COUNT, MAX_COUNT)] long lSize,
    [out,size_is(lSize)] UserDataType * pArr
    );
    

    Nesse caso, o cliente fornece um buffer de tamanho fixo para pArr , permitindo que o serviço RPC do lado do servidor aloque um buffer de tamanho razoável com um bom grau de garantia. Observe que no exemplo os dados são recebidos do servidor ([out]). A definição é semelhante para os dados passados para o servidor ([em]).

  • Para situações em que o componente do lado do servidor de um aplicativo RPC decide o comprimento dos dados, a definição do método deve ser semelhante à seguinte:

    typedef [range(MIN_COUNT,MAX_COUNT)] long RANGED_LONG;
    
    outUnknownSize
    (
    [out] RANGED_LONG *pSize,
    [out,size_is(,*pSize)] UserDataType **ppArr
    );
    

    RANGED_LONG é um tipo definido para os stubs de cliente e servidor e de um tamanho especificado que o cliente pode prever corretamente. No exemplo, o cliente passa ppArr como NULL e o componente de aplicativo de servidor RPC aloca a quantidade correta de memória. Após o retorno, o serviço RPC no lado do cliente aloca a memória para os dados retornados.

  • Se o cliente quiser enviar um subconjunto de uma grande matriz conforme para o servidor, o aplicativo pode especificar o tamanho do subconjunto, conforme demonstrado no exemplo a seguir:

    inConformantVaryingArray
    (
    [in,range(MIN_COUNT,MAX_COUNT)] long lSize,
    [in] long lLength, 
    [in,size_is(lSize), length_is(lLength)] UserDataType *pArr
    );
    

    Desta forma, o RPC transmitirá apenas lLength elementos da matriz através do fio. No entanto, essa definição força o serviço RPC a alocar memória de tamanho lSize no lado do servidor.

  • Se o componente de aplicativo cliente determinar o tamanho máximo de uma matriz que o servidor pode retornar, mas permitir que o servidor transmita um subconjunto dessa matriz, o aplicativo poderá especificar tal comportamento definindo o IDL semelhante ao exemplo a seguir:

    inMaxSizeOutLength
    (
    [in, range(MIN_COUNT, MAX_COUNT)] long lSize,
    [out] long *pLength,
    [out,size_is(lSize), length_is(*pLength)] UserDataType *pArr
    );
    

    O componente de aplicativo cliente especifica o tamanho máximo da matriz e o servidor especifica quantos elementos ele transmite de volta ao cliente.

  • Se o componente de aplicativo de servidor precisar retornar uma cadeia de caracteres para o componente de aplicativo cliente e se o cliente souber o tamanho máximo a ser retornado do servidor, o aplicativo poderá usar um tipo de cadeia de caracteres conforme, conforme demonstrado no exemplo a seguir:

    outStringKnownSize
    (
    [in,range(MIN_COUNT, MAX_STRING)] long lSize,
    [out,size_is(lSize),string] wchar_t *pString
    );
    
  • Se o componente de aplicativo cliente não deve controlar o tamanho da cadeia de caracteres, o serviço RPC pode alocar especificamente a memória, conforme demonstrado no exemplo a seguir:

    outStringUnknownSize
    (
    [out] LPWSTR *ppStr
    );
    

    O componente de aplicativo cliente deve definir ppStr para NULL ao chamar o método RPC.