Compartilhar via


Técnicas de IDL para melhor interface e design de método

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

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

O atributo [intervalo] instrui o tempo de execução do RPC a executar validação de tamanho adicional durante o processo de desempacotamento de dados. Especificamente, 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 sobrecargas de buffer. Da mesma forma, usar [range] pode melhorar o desempenho do aplicativo, pois os dados de conformidade marcados com ele têm restrições claramente definidas como 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 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 [range] em conjunto com dados de conformidade, conforme indicado acima, bem como evitar deliberadamente a aplicação de atributos de IDL de dados de comprimento variável, como [length_is] a dados de conformidade.

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

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

Veja a seguir 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 a correlação inicial. Geralmente, é melhor definir o parâmetro ou campo de tamanho variável, de modo que ele 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 que

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

    wherein earlyCorr declara o parâmetro de tamanho imediatamente antes do parâmetro de dados de comprimento variável e lateCorr declara o parâmetro de tamanho após ele. O uso de correspondência antecipada 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 ao seguinte em termos de atribuição de parâmetro e sequência:

    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 aos dados passados para o servidor ([in]).

  • 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 do cliente e do 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 do 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 de conformidade para o servidor, o aplicativo poderá 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
    );
    

    Dessa forma, o RPC transmitirá apenas elementos lLength da matriz pelo 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 do 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 esse comportamento definindo a 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 para o cliente.

  • Se o componente de aplicativo do 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 compatível, 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 do aplicativo cliente não deve controlar o tamanho da cadeia de caracteres, o serviço RPC poderá alocar especificamente a memória, conforme demonstrado no exemplo a seguir:

    outStringUnknownSize
    (
    [out] LPWSTR *ppStr
    );
    

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