Beispiel #1
0
        // ------------------------------------------------------
        //
        // Internal Methods
        //
        // ------------------------------------------------------
        // Update the Array of hwnd requesting notifications
        // Param name="hwnd"
        // Param name="raiseEvents" - function to call to create a raw element
        // Param name="aEvtIdProp"
        // Param name="cProps" - Number of valid props in the array
        static internal void AddToNotificationList (IntPtr hwnd, ProxyRaiseEvents raiseEvents, EvtIdProperty[] aEvtIdProp, int cProps)
        {
            GetCallbackQueue();

            // Build the list of Event to Window List
            BuildEventsList (EventFlag.Add, hwnd, raiseEvents, aEvtIdProp, cProps);
        }
        // Update the Array of hwnd requesting notifications
        //      eFlag - Add or Remove
        //      hwnd
        //      raiseEvents - function to call to create a raw element
        //      aEvtIdProp - Array of Tupples WinEvent and Automation properties
        //      cProps  - Number of valid props in the array
        private static void BuildEventsList(EventFlag eFlag, IntPtr hwnd, ProxyRaiseEvents raiseEvents, EvtIdProperty[] aEvtIdProp, int cProps)
        {
            // All operations in the list of events and windows handle must be atomic
            lock (_ahp)
            {
                for (int i = 0; i < cProps; i++)
                {
                    EvtIdProperty evtIdProp = aEvtIdProp[i];

                    // Map a property into a WinEventHookProperty
                    int evt = Array.BinarySearch(_eventIdToIndex, evtIdProp._evtId);

                    // add the window to the list
                    if (evt >= 0)
                    {
                        EventHookParams hookParams = null;

                        uint processId;

                        if (hwnd == IntPtr.Zero)
                        {
                            // if its a global event use this well known key to the hash
                            processId = _globalEventKey;
                        }
                        else
                        {
                            if (Misc.GetWindowThreadProcessId(hwnd, out processId) == 0)
                            {
                                processId = _globalEventKey;
                            }
                        }

                        // If never seens this EventId before. Create the notification object
                        if (_ahp[evt] == null)
                        {
                            // create the hash table the key is the process id
                            _ahp[evt] = new Hashtable(10);
                        }

                        // Find the EventHookParams.
                        // _ahp is an array of Hashtables where each Hashtable corrasponds to one event.
                        // Get the correct Hashtable using the index evt.  Then lookup the EventHookParams
                        // in the hash table, using the process id.
                        hookParams = (EventHookParams)_ahp[evt][processId];

                        // If there is not an entry for the event for the specified process then create one.
                        if (hookParams == null)
                        {
                            hookParams          = new EventHookParams();
                            hookParams._process = processId;
                            _ahp[evt].Add(processId, hookParams);
                        }

                        ArrayList eventCreateParams = hookParams._alHwnd;

                        if (eFlag == EventFlag.Add)
                        {
                            if (eventCreateParams == null)
                            {
                                // empty array, create the hwnd arraylist
                                hookParams._evtId = evtIdProp._evtId;
                                eventCreateParams = hookParams._alHwnd = new ArrayList(16);
                            }

                            // Check if the event for that window already exist.
                            // Discard it as no dups are allowed
                            for (int index = eventCreateParams.Count - 1; index >= 0; index--)
                            {
                                EventCreateParams ecp = (EventCreateParams)eventCreateParams[index];

                                // Code below will discard duplicates:
                                // Proxy cannot subscribe same hwnd to the same event more than once
                                // However proxy can be globaly registered to be always notified of some event, in order to
                                // do this proxy will send IntPtr.Zero as hwnd. Please notice that a given Proxy can be globaly registered
                                // to some EVENT_XXX only once. This will be ensured via delegate comparison.
                                if ((hwnd == IntPtr.Zero || ecp._hwnd == hwnd) &&
                                    ecp._idProp == evtIdProp._idProp &&
                                    ecp._raiseEventFromRawElement == raiseEvents)
                                {
                                    return;
                                }
                            }

                            // Set the WinEventHook if first time around
                            if (eventCreateParams.Count == 0)
                            {
                                _callbackQueue.PostSyncWorkItem(new QueueItem.WinEventItem(ref hookParams, _startDelegate));
                            }

                            // add the event into the list
                            // Called after the Post does not matter because of the lock
                            eventCreateParams.Add(new EventCreateParams(hwnd, evtIdProp._idProp, raiseEvents));
                        }
                        else
                        {
                            if (eventCreateParams == null)
                            {
                                return;
                            }

                            // Remove a notification
                            // Go through the list of window to find the one
                            for (int index = eventCreateParams.Count - 1; index >= 0; index--)
                            {
                                EventCreateParams ecp = (EventCreateParams)eventCreateParams[index];

                                // Detect if caller should be removed from notification list
                                bool remove = false;

                                if (raiseEvents == null)
                                {
                                    // Not a global wide events
                                    remove = (ecp._hwnd == hwnd && ecp._idProp == evtIdProp._idProp);
                                }
                                else
                                {
                                    // Global events
                                    Debug.Assert(hwnd == IntPtr.Zero, @"BuildEventsList: event is global but hwnd is not null");
                                    remove = (ecp._hwnd == hwnd && ecp._raiseEventFromRawElement == raiseEvents);
                                }

                                if (remove)
                                {
                                    eventCreateParams.RemoveAt(index);

                                    // if empty then stop listening for this event arg
                                    if (eventCreateParams.Count == 0)
                                    {
                                        _callbackQueue.PostSyncWorkItem(new QueueItem.WinEventItem(ref hookParams, _stopDelegate));
                                        _ahp[evt].Remove(processId);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #3
0
 // Update the Array of hwnd requesting notifications calling the main routine
 // Param name="hwnd"
 // Param name="raiseEvents" - Callback, should be null for non system-wide events
 // Param name="aEvtIdProp"
 // Param name="cProps" - Number of valid props in the array
 static internal void RemoveToNotificationList (IntPtr hwnd, EvtIdProperty[] aEvtIdProp, ProxyRaiseEvents raiseEvents, int cProps)
 {
     // Remove the list of Event to Window List
     // NOTE: raiseEvents must be null in the case when event is not a system-wide event
     BuildEventsList (EventFlag.Remove, hwnd, raiseEvents, aEvtIdProp, cProps);
 }
Beispiel #4
0
        // Update the Array of hwnd requesting notifications
        //      eFlag - Add or Remove
        //      hwnd
        //      raiseEvents - function to call to create a raw element
        //      aEvtIdProp - Array of Tupples WinEvent and Automation properties
        //      cProps  - Number of valid props in the array
        private static void BuildEventsList (EventFlag eFlag, IntPtr hwnd, ProxyRaiseEvents raiseEvents, EvtIdProperty[] aEvtIdProp, int cProps)
        {
            // All operations in the list of events and windows handle must be atomic
            lock (_ahp)
            {
                for (int i = 0; i < cProps; i++)
                {
                    EvtIdProperty evtIdProp = aEvtIdProp[i];

                    // Map a property into a WinEventHookProperty
                    int evt = Array.BinarySearch (_eventIdToIndex, evtIdProp._evtId);

                    // add the window to the list
                    if (evt >= 0)
                    {
                        EventHookParams hookParams = null;
                        
                        uint processId;

                        if (hwnd == IntPtr.Zero)
                        {
                            // if its a global event use this well known key to the hash
                            processId = _globalEventKey;
                        }
                        else
                        {
                            if (Misc.GetWindowThreadProcessId(hwnd, out processId) == 0)
                            {
                                processId = _globalEventKey;
                            }
                        }

                        // If never seens this EventId before. Create the notification object
                        if (_ahp[evt] == null)
                        {
                            // create the hash table the key is the process id
                            _ahp[evt] = new Hashtable(10);
                        }

                        // Find the EventHookParams.  
                        // _ahp is an array of Hashtables where each Hashtable corrasponds to one event.
                        // Get the correct Hashtable using the index evt.  Then lookup the EventHookParams
                        // in the hash table, using the process id.
                        hookParams = (EventHookParams)_ahp[evt][processId];

                        // If there is not an entry for the event for the specified process then create one.
                        if (hookParams == null)
                        {
                            hookParams = new EventHookParams();
                            hookParams._process = processId;
                            _ahp[evt].Add(processId, hookParams);
                        }

                        ArrayList eventCreateParams = hookParams._alHwnd;

                        if (eFlag == EventFlag.Add)
                        {
                            if (eventCreateParams == null)
                            {
                                // empty array, create the hwnd arraylist
                                hookParams._evtId = evtIdProp._evtId;
                                eventCreateParams = hookParams._alHwnd = new ArrayList (16);
                            }

                            // Check if the event for that window already exist.
                            // Discard it as no dups are allowed
                            for (int index = eventCreateParams.Count - 1; index >= 0; index--)
                            {
                                EventCreateParams ecp = (EventCreateParams)eventCreateParams[index];

                                // Code below will discard duplicates:
                                // Proxy cannot subscribe same hwnd to the same event more than once
                                // However proxy can be globaly registered to be always notified of some event, in order to
                                // do this proxy will send IntPtr.Zero as hwnd. Please notice that a given Proxy can be globaly registered 
                                // to some EVENT_XXX only once. This will be ensured via delegate comparison.
                                if ( (hwnd == IntPtr.Zero || ecp._hwnd == hwnd) && 
                                     ecp._idProp == evtIdProp._idProp && 
                                     ecp._raiseEventFromRawElement == raiseEvents)
                                {
                                    return;
                                }
                            }

                            // Set the WinEventHook if first time around
                            if (eventCreateParams.Count == 0)
                            {
                                _callbackQueue.PostSyncWorkItem (new QueueItem.WinEventItem (ref hookParams, _startDelegate));
                            }
                            
                            // add the event into the list
                            // Called after the Post does not matter because of the lock
                            eventCreateParams.Add (new EventCreateParams (hwnd, evtIdProp._idProp, raiseEvents));
                        }
                        else
                        {
                            if ( eventCreateParams == null )
                                return;
                            
                            // Remove a notification
                            // Go through the list of window to find the one
                            for (int index = eventCreateParams.Count - 1; index >= 0; index--)
                            {
                                EventCreateParams ecp = (EventCreateParams)eventCreateParams[index];

                                // Detect if caller should be removed from notification list
                                bool remove = false;

                                if (raiseEvents == null)
                                {
                                    // Not a global wide events                                    
                                    remove = (ecp._hwnd == hwnd && ecp._idProp == evtIdProp._idProp);
                                }
                                else
                                {
                                    // Global events
                                    Debug.Assert (hwnd == IntPtr.Zero, @"BuildEventsList: event is global but hwnd is not null");
                                    remove = (ecp._hwnd == hwnd && ecp._raiseEventFromRawElement == raiseEvents);
                                }

                                if (remove)
                                {
                                    eventCreateParams.RemoveAt (index);

                                    // if empty then stop listening for this event arg
                                    if (eventCreateParams.Count == 0)
                                    {
                                        _callbackQueue.PostSyncWorkItem (new QueueItem.WinEventItem (ref hookParams, _stopDelegate));
                                        _ahp[evt].Remove(processId);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }