/** @file AppleEventDxe Copyright (c) 2018, vit9696 All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include #include #include #include #include #include #include #include #include "AppleEventInternal.h" // APPLE_EVENT_QUEUE_SIGNATURE #define APPLE_EVENT_QUEUE_SIGNATURE SIGNATURE_32 ('A', 'E', 'v', 'Q') // APPLE_EVENT_QUEUE_FROM_LIST_ENTRY #define APPLE_EVENT_QUEUE_FROM_LIST_ENTRY(ListEntry) \ CR ((ListEntry), APPLE_EVENT_QUEUE, Link, APPLE_EVENT_QUEUE_SIGNATURE) // APPLE_EVENT_QUEUE typedef struct { UINT32 Signature; ///< LIST_ENTRY Link; ///< APPLE_EVENT_INFORMATION *Information; ///< } APPLE_EVENT_QUEUE; // mQueueEvent STATIC EFI_EVENT mQueueEvent = NULL; // mQueueEventCreated STATIC BOOLEAN mQueueEventCreated = FALSE; // mEventQueueList STATIC LIST_ENTRY mQueue = INITIALIZE_LIST_HEAD_VARIABLE (mQueue); // mQueueLock STATIC EFI_LOCK mQueueLock = { 0, 0, FALSE }; // InternalSignalAndCloseQueueEvent VOID InternalSignalAndCloseQueueEvent ( VOID ) { DEBUG ((DEBUG_VERBOSE, "InternalSignalAndCloseQueueEvent\n")); gBS->SignalEvent (mQueueEvent); if (mQueueEventCreated && (mQueueEvent != NULL)) { gBS->CloseEvent (mQueueEvent); } } // InternalQueueEventNotifyFunction STATIC VOID EFIAPI InternalQueueEventNotifyFunction ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; LIST_ENTRY *EventQueueEntry; APPLE_EVENT_QUEUE *EventQueue; DEBUG ((DEBUG_VERBOSE, "InternalQueueEventNotifyFunction\n")); if (mQueueEventCreated) { do { Status = EfiAcquireLockOrFail (&mQueueLock); } while (EFI_ERROR (Status)); InternalFlagAllEventsReady (); EventQueueEntry = GetFirstNode (&mQueue); while (!IsNull (&mQueue, EventQueueEntry)) { EventQueue = APPLE_EVENT_QUEUE_FROM_LIST_ENTRY (EventQueueEntry); InternalSignalEvents (EventQueue->Information); if ( ((EventQueue->Information->EventType & APPLE_ALL_KEYBOARD_EVENTS) != 0) && (EventQueue->Information->EventData.KeyData != NULL)) { FreePool ( (VOID *)EventQueue->Information->EventData.KeyData ); } EventQueueEntry = RemoveEntryList (EventQueueEntry); FreePool ((VOID *)EventQueue->Information); FreePool ((VOID *)EventQueue); } InternalRemoveUnregisteredEvents (); EfiReleaseLock (&mQueueLock); } } // InternalCreateQueueEvent VOID InternalCreateQueueEvent ( VOID ) { EFI_STATUS Status; DEBUG ((DEBUG_VERBOSE, "InternalCreateQueueEvent\n")); EfiInitializeLock (&mQueueLock, TPL_NOTIFY); Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, InternalQueueEventNotifyFunction, NULL, &mQueueEvent ); if (!EFI_ERROR (Status)) { mQueueEventCreated = TRUE; } } // EventCreateAppleEventQueueInfo APPLE_EVENT_INFORMATION * EventCreateAppleEventQueueInfo ( IN APPLE_EVENT_DATA EventData, IN APPLE_EVENT_TYPE EventType, IN DIMENSION *PointerPosition, IN APPLE_MODIFIER_MAP Modifiers ) { APPLE_EVENT_INFORMATION *QueueInfo; EFI_TIME CreationTime; DEBUG ((DEBUG_VERBOSE, "EventCreateAppleEventQueueInfo\n")); QueueInfo = AllocateZeroPool (sizeof (*QueueInfo)); if (QueueInfo != NULL) { gRT->GetTime (&CreationTime, NULL); QueueInfo->EventType = EventType; QueueInfo->EventData = EventData; QueueInfo->Modifiers = Modifiers; QueueInfo->CreationTime.Year = CreationTime.Year; QueueInfo->CreationTime.Month = CreationTime.Month; QueueInfo->CreationTime.Day = CreationTime.Day; QueueInfo->CreationTime.Hour = CreationTime.Hour; QueueInfo->CreationTime.Minute = CreationTime.Minute; QueueInfo->CreationTime.Second = CreationTime.Second; QueueInfo->CreationTime.Pad1 = CreationTime.Pad1; if (PointerPosition != NULL) { CopyMem ( (VOID *)&QueueInfo->PointerPosition, (VOID *)PointerPosition, sizeof (*PointerPosition) ); } } else { DEBUG ((DEBUG_VERBOSE, "EventCreateAppleEventQueueInfo alloc failure\n")); } return QueueInfo; } // EventAddEventToQueue VOID EventAddEventToQueue ( IN APPLE_EVENT_INFORMATION *Information ) { EFI_STATUS Status; APPLE_EVENT_QUEUE *EventQueue; DEBUG ((DEBUG_VERBOSE, "EventAddEventToQueue\n")); if (mQueueEventCreated) { do { Status = EfiAcquireLockOrFail (&mQueueLock); } while (EFI_ERROR (Status)); EventQueue = AllocateZeroPool (sizeof (*EventQueue)); if (EventQueue != NULL) { EventQueue->Signature = APPLE_EVENT_QUEUE_SIGNATURE; EventQueue->Information = Information; InsertTailList (&mQueue, &EventQueue->Link); } else { DEBUG ((DEBUG_VERBOSE, "EventAddEventToQueue alloc failure\n")); } EfiReleaseLock (&mQueueLock); gBS->SignalEvent (mQueueEvent); } } // EventCreateEventQueue EFI_STATUS EventCreateEventQueue ( IN APPLE_EVENT_DATA EventData, IN APPLE_EVENT_TYPE EventType, IN APPLE_MODIFIER_MAP Modifiers ) { EFI_STATUS Status; APPLE_EVENT_INFORMATION *Information; DEBUG ((DEBUG_VERBOSE, "EventCreateEventQueue\n")); Status = EFI_INVALID_PARAMETER; if ((EventData.Raw != 0) || (Modifiers != 0)) { Information = EventCreateAppleEventQueueInfo ( EventData, EventType, NULL, Modifiers ); Status = EFI_OUT_OF_RESOURCES; if (Information != NULL) { EventAddEventToQueue (Information); Status = EFI_SUCCESS; } else { DEBUG ((DEBUG_VERBOSE, "EventCreateEventQueue alloc failure\n")); } } return Status; }