Compartilhar via


Serviços Win32 interagindo com dispositivos

Um serviço Win32 ideal instalado por meio do InF AddService que interage com dispositivos se comporta de forma semelhante à maneira como um driver interage com dispositivos. Um driver é carregado e descarregado dependendo da presença de um dispositivo e um serviço Win32 que interage com dispositivos deve seguir esse mesmo padrão de iniciar e parar dependendo da presença de um dispositivo.

Os serviços devem começar somente quando uma interface do dispositivo estiver presente e habilitada para interagir e parar quando a interface do dispositivo não estiver mais habilitada. Esse padrão de design garante um serviço robusto que minimiza o comportamento indesejado e indefinido. Veremos como um serviço deve ser projetado para seguir esse padrão.

Instalação do serviço

Para instalar o serviço, use a diretiva AddService do INF . Isso permitirá que você crie e inicie o serviço.

Adicione a configuração que faz o serviço iniciar a demanda. Isso pode ser feito definindo StartType=0x3 que faz com que o gatilho de serviço seja iniciado.

A etapa final nesta seção é usar a diretiva AddTrigger para fazer com que o serviço seja iniciado quando uma interface do dispositivo chegar (consulte AddService para obter mais detalhes sobre AddTrigger). Veja abaixo um exemplo de como AddTrigger deve ser usado:

[UserSvc_Install]
ServiceType   = 0x10 ; SERVICE_WIN32_OWN_PROCESS
StartType     = 3    ; SERVICE_DEMAND_START
ErrorControl  = 0    ; SERVICE_ERROR_IGNORE
ServiceBinary = %13%\oemsvc.exe
AddTrigger    = UserSvc_AddTrigger

[UserSvc_AddTrigger]
TriggerType = 1                           ; SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL
Action      = 1                           ; SERVICE_TRIGGER_ACTION_SERVICE_START
SubType     = %GUID_DEVINTERFACE_OSRFX2%  ; Interface class GUID
DataItem    = 2, "USB\VID_0547&PID_1002"  ; SERVICE_TRIGGER_DATA_TYPE_STRING

Observe que a HardwareId especificada no DataItem é opcional e geralmente só é necessária ao usar uma interface de classe genérica para definir o escopo do gatilho para um dispositivo mais específico.

Runtime de serviço

Do ponto de vista do runtime, a primeira etapa do serviço deve ser registrar-se para notificações de interface do dispositivo. Diretrizes prescritivas sobre como fazer isso podem ser encontradas nesta página: Registrando-se para notificação de chegada da interface do dispositivo e remoção de dispositivo.

Em particular, você deve usar CM_Register_Notification com o sinalizador CM_NOTIFY_FILTERY_TYPE_DEVICEINTERFACE para realizar o registro apropriado de notificações de interface do dispositivo.

Observação

Quando um serviço está sendo iniciado, você não pode contar com o fato de que receberá notificações de interface do dispositivo, pois a notificação de chegada pode já ter passado, especialmente se a chegada de uma interface do dispositivo for a causa do início do serviço. Em vez disso, você deve obter uma lista de interfaces de dispositivo para marcar se já houver interfaces presentes.

Depois de se registrar para notificações para interfaces de dispositivo, você será notificado sobre novas interfaces de dispositivo sendo habilitadas ou interfaces de dispositivo existentes sendo desabilitadas. Você pode descobrir o caminho da interface do dispositivo no retorno de chamada de notificação. Para consultar a lista de interfaces de dispositivo existentes para examinar interfaces de dispositivo que existiam antes do serviço ser iniciado e registrado para notificações, você pode obter uma lista de interfaces de dispositivo por meio de APIs como CM_Get_Device_Interface_List.

Observação

Há uma chance de que a interface do dispositivo chegue entre o registro de notificações e a recuperação de uma lista de interfaces de dispositivo já existentes no sistema. Nesse caso, a interface do dispositivo será listada no retorno de chamada de notificação e na lista de interfaces do dispositivo.

Se você quiser interagir com a interface do dispositivo com APIs de E/S, depois de encontrar a interface de dispositivo desejada, abra um identificador para a interface por meio de CreateFile.

A próxima etapa é registrar notificações secundárias por identificador para ser notificado sobre alterações de estado no dispositivo, como tentativas de consultar remover o dispositivo ou o dispositivo que está desaparecendo. Isso pode ser feito usando CM_Register_Notification com o sinalizador CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE . Seguindo as diretrizes em Registrar-se para Notificação de Chegada da Interface do Dispositivo e Remoção de Dispositivo garantirá que, quando um dispositivo estiver desaparecendo, o identificador possa ser liberado adequadamente.

As chegadas e remoções da interface do dispositivo devem ser controladas para que a remoção da última interface do dispositivo com a qual o serviço possa querer interagir significa que o serviço pode ser interrompido. Depois que a última interface tiver sido removida, interrompa o serviço (informações detalhadas podem ser encontradas nesta página). Isso pode ser feito seguindo estas etapas:

  1. Postar SERVICE_STOP_PENDING estado no SCM para indicar que o serviço está desativando

  2. Não inicializar/limpo tudo o que o serviço estava usando

  3. Postar SERVICE_STOP estado no SCM para concluir a operação de parada

Se o serviço estiver sendo interrompido, certifique-se de marcar e percorrer todas as alças abertas existentes para interfaces de dispositivo (pode não haver nenhuma) e limpo-las.

A interface do dispositivo pode voltar durante a instalação do dispositivo, habilitar/desabilitar o dispositivo, reennumeração do dispositivo, reinicialização do sistema ou durante outros cenários não listados. Quando a interface do dispositivo voltar, o serviço será iniciado com base no registro de início do gatilho.

Esse fluxo garantirá que o serviço comece na chegada de uma interface do dispositivo e pare quando a última interface do dispositivo não estiver mais presente.

Há um exemplo no GitHub que explica como um serviço pode aproveitar esse fluxo de eventos. O exemplo pode ser encontrado aqui: Exemplo de serviço Win32.

Além disso, você pode encontrar uma documentação útil sobre AddTrigger na página AddService .