Filtragem de notificação e estilos de comunicação
Esta seção descreve a interface entre o processo do spooler e os componentes de impressão, como o processador de impressão, o driver e o monitor.
Filtragem de notificação
O tipo enumerado PrintAsyncNotifyUserFilter é usado para duas situações. No primeiro deles, um componente de impressão em execução dentro do spooler chama a função CreatePrintAsyncNotifyChannel para criar um canal de notificação. O chamador passa um enumerador do tipo enumerado PrintAsyncNotifyUserFilter para especificar quais clientes ouvintes têm permissão para receber notificações. Na segunda situação, um cliente ouvinte chama a função RegisterForPrintAsyncNotifications para se registrar para notificação. O chamador passa um dos enumeradores PrintAsyncNotifyUserFilter para indicar quais notificações ele deve receber.
typedef enum
{
kPerUser,
kAllUsers
} PrintAsyncNotifyUserFilter;
Na figura a seguir, o enumerador kPerUser é usado na chamada para a função CreatePrintAsyncNotifyChannel . Como resultado, somente os ouvintes em execução na mesma conta de usuário que o usuário que fez o registro têm permissão para receber notificações.
Na próxima figura, o enumerador kAllUsers é usado na chamada para a função CreatePrintAsyncNotifyChannel . Como resultado, todos os ouvintes interessados na impressora ou no servidor podem receber notificações. Observe que somente os administradores têm permissão para usar a configuração kAllUsers em chamadas para essa função.
A figura a seguir mostra a situação em que o Usuário 1 e o Usuário 2 se registraram para notificações chamando a função RegisterForPrintAsyncNotifications , passando o enumerador kPerUser na chamada. Das três notificações enviadas, o ouvinte Usuário 1 recebe notificações do Usuário 1 na sessão 0 ou na sessão 1. O Ouvinte Usuário 2 recebe notificações do Usuário 2 na sessão 2.
Se os clientes ouvintes mostrados na figura anterior tivessem chamado RegisterForPrintAsyncNotifications, mas desta vez passando o enumerador kAllUsers na chamada, todos os ouvintes em todas as sessões teriam recebido as três notificações. Observe que somente os administradores têm permissão para usar o enumerador kAllUsers em chamadas para essa função.
Administradores
Um administrador é um usuário com direitos de PRINTER_ACCESS_ADMINISTER para o objeto de impressão especificado. Um administrador pode enviar notificações para qualquer pessoa e pode receber notificações de qualquer pessoa. Observe que o filtro de notificação ainda é imposto.
Na figura a seguir, Joe envia uma notificação em um canal com um kPerUser. Quando o canal é filtrado com base nesse enumerador, a notificação deve ser enviada somente para sessões que pertencem ao Usuário 1, ou seja, a sessão 1. No entanto, a notificação também é enviada para a sessão 2, porque há um administrador escutando lá e está escutando notificações desse tipo. Observe que o administrador na sessão 3 não recebe a notificação, pois os tipos de notificação não são os mesmos.
Especificando o tipo de comunicação
Ao especificar um tipo de comunicação, o componente de impressão indica se uma resposta é esperada do cliente ouvinte, bem como a maneira como o spooler lida com o caso quando as notificações são enviadas de volta de vários clientes.
typedef enum
{
kBidirectional = 1,
kUnidirectional,
} PrintAsyncNotifyConversationStyle
Há dois tipos de comunicação: unidirecional e bidirecional. Na comunicação unidirecional, um cliente ouvinte não responde a uma notificação de spooler. Nesse caso, o cliente ouvinte não pode enviar notificações de volta porque recebe um ponteiro de interface NULL IPrintAsyncNotifyChannel. Na comunicação bidirecional, o cliente envia uma resposta quando recebe uma notificação e executa uma caixa de diálogo com o componente de impressão. Esse é o caso de notificação da interface do usuário.
A situação em que várias sessões recebem uma notificação de interface do usuário merece comentários. Nessa situação, o spooler abre um canal e notifica todos os ouvintes que correspondem aos filtros, enviando-lhes a primeira notificação. Quando o primeiro ouvinte responde, o spooler fecha os outros canais e a caixa de diálogo continua com o primeiro cliente.
Se um administrador (por exemplo) fizer logon antes que um cliente de escuta registrado responda, o administrador receberá a mesma notificação de interface do usuário que o cliente ouvinte.
Quando o primeiro usuário (o administrador, por exemplo) envia a resposta, o spooler marca as conexões com os outros clientes como "fechadas". Quando o outro cliente ouvinte eventualmente responde, ele recebe uma mensagem de "canal fechado".
Tipos de notificação
O tipo de notificação é um GUID que o spooler aceita e usa para filtrar os clientes ouvintes. (Consulte a definição do tipo PrintAsyncNotificationType no arquivo de cabeçalho Prnasnot.h.) Qualquer cliente do mecanismo de notificação assíncrona do spooler pode definir seu próprio tipo de notificação. Embora o spooler não saiba o significado do tipo de notificação enviado, ele ainda filtra os clientes ouvintes com base no tipo de notificação.
Cada notificação deve ter um tipo de dados de notificação associado a ela. Esse tipo identifica o esquema de dados de notificação.
Além do tipo de dados de notificação, há um tipo associado ao canal, o tipo de canal de notificação. Um remetente de notificação e um cliente ouvinte usam o tipo de canal de notificação para diferentes finalidades.
No lado do remetente do canal, quando um componente de impressão abre um canal, ele pode especificar o tipo de notificações que pretende enviar por esse canal. Todas as notificações que passam por esse canal devem ser do mesmo tipo que o tipo de canal de notificação.
O remetente sempre deve associar um tipo a uma notificação para que o spooler "saiba" como enviá-lo aos clientes ouvintes apropriados. Um cliente ouvinte deve validar os dados de acordo com seu próprio esquema. O tipo de notificação identifica esse esquema.
No lado do ouvinte do canal, um cliente ouvinte pode pedir para receber um tipo de notificação especificando um determinado tipo de dados de notificação quando ele se registra.
O spooler define um tipo de notificação especial usado para anunciar aos clientes ouvintes que o serviço ou o aplicativo morreu.
const GUID NOTIFICATION_RELEASE;
O cliente ouvinte pode receber esse tipo de mensagem somente quando o método IPrintAsyncNotifyCallback::ChannelClosed for chamado.
Identificador de Registro de Notificação
Quando um cliente se registra para notificações, o spooler do lado do servidor mantém uma tabela interna com informações sobre o aplicativo, como seu contexto de segurança. O identificador de registro de notificação é uma estrutura opaca que o cliente recebe.
O cliente pode cancelar o registro para receber notificações somente usando esse identificador.