Comment savoir si un object événement du kernel Windows est réinitialisé automatiquement ou manuellement?

Windows permet la création d’ objects Event (nommés).

Un événement (la primitive de synchronisation dans Windows) peut être de type réinitialisation automatique (auquel cas vous pouvez dire que c’est un sémaphore ) ou il peut être de type réinitialisation manuelle, auquel cas il rest défini jusqu’à ce que quelqu’un le réinitialise.

Maintenant, à partir de docs pour CreateEvent , OpenEvent , SetEvent , etc., il semble qu’il n’y ait aucun moyen de déterminer, une fois que l’événement a été créé, s’il est réinitialisé automatiquement ou maual-reset.

Je suis dans la situation, où un processus crée un événement nommé et un deuxième processus devra fonctionner sur cet événement (il reçoit le nom, puis ouvre l’événement et le signale éventuellement). Étant donné que l’événement devrait toujours être un événement de réinitialisation manuelle pour que tout ait un sens, j’aurais aimé append une vérification dans le 2ème processus pour m’assurer qu’il s’agit d’ un événement de réinitialisation manuelle. Est-il possible de vérifier cela?

(Et oui, il s’agit plutôt d’un élément intéressant dans ma situation, car ce serait un bogue de toute façon si un code créait un événement de réinitialisation automatique et le transmettait à ce processus. Mais des bogues surviennent, et mieux si Je peux les détecter.)

Il n’y a aucun moyen documenté de le faire, mais en réalité, ce n’est pas difficile si vous vous aventurez dans des terres sans papiers. (Pour vos besoins, cela devrait aller, car cela n’affecte pas vraiment la fonctionnalité de votre programme.)

La première chose à faire est de savoir si la poignée qui vous est donnée est un événement ou non. Vous utilisez NtQueryObject pour cela. La fonction est documentée ici: http://msdn.microsoft.com/en-us/library/bb432383(v=vs.85).aspx . Il est livré avec les conditions habituelles pour les API natives selon lesquelles il pourrait disparaître ou changer sans préavis. Exemple partiel:

#include  typedef NTSTATUS (NTAPI * PFN_NtQueryObject)( HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength ); HMODULE ntdll = GetModuleHandle( L"ntdll.dll" ); auto NtQueryObject = (PFN_NtQueryObject)GetProcAddress( ntdll, "NtQueryObject" ); NTSTATUS result = NtQueryObject( eventHandle, ObjectTypeInformation, buffer, length, &length ); 

Cela vous donnera une structure PUBLIC_OBJECT_TYPE_INFORMATION. Le champ TypeName sera “Event” si l’object est réellement un événement.

Ensuite, vous appelez NtQueryEvent pour obtenir le type de l’événement. Tout cela est complètement sans papiers.

 typedef enum _EVENT_INFORMATION_CLASS { EventBasicInformation } EVENT_INFORMATION_CLASS, *PEVENT_INFORMATION_CLASS; typedef enum _EVENT_TYPE { NotificationEvent, SynchronizationEvent } EVENT_TYPE, *PEVENT_TYPE; typedef struct _EVENT_BASIC_INFORMATION { EVENT_TYPE EventType; LONG EventState; } EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION; typedef NTSTATUS (NTAPI * PFN_NtQueryEvent)( HANDLE EventHandle, EVENT_INFORMATION_CLASS EventInformationClass, PVOID EventInformation, ULONG EventInformationLength, PULONG ReturnLength ); auto NtQueryEvent = (PFN_NtQueryEvent)GetProcAddress( ntdll, "NtQueryEvent" ); EVENT_BASIC_INFORMATION info; ULONG length = sizeof( info ); NTSTATUS result = NtQueryEvent( eventHandle, EventBasicInformation, &info, length, &length ); 

Maintenant, examinez simplement le champ EventType dans l’info et vous avez terminé. “NotificationEvent” signifie réinitialisation manuelle et “SynchronizationEvent” signifie réinitialisation automatique.

Si vous vous demandez comment j’ai compris cette seconde partie, je ne l’ai pas fait. L’information vient d’ici: http://undocumented.ntinternals.net/ . S’il vous plaît utiliser de manière responsable!

Appelez WaitForSingleObject( handle, 0 ) immédiatement après le retour de votre WaitForSingleObject initial. Si la valeur WAIT_TIMEOUT est WAIT_TIMEOUT vous savez qu’il s’agit d’un événement de réinitialisation automatique, s’il s’agit de WAIT_OBJECT_0 qui sera renvoyé et qu’il s’agit d’un événement de réinitialisation manuelle.

Cela suppose que le descripteur soit défini entre les deux appels, il existe donc une condition de concurrence potentielle dans laquelle il ne détecte pas d’événement de réinitialisation automatique, mais il devrait fonctionner la plupart du temps. Comme c’est bon à avoir, espérons-le, cela suffit?