|
| 1 | +/* |
| 2 | + * Copyright (C) 2007-2008 Alacatia Labs |
| 3 | + * |
| 4 | + * This software is provided 'as-is', without any express or implied |
| 5 | + * warranty. In no event will the authors be held liable for any damages |
| 6 | + * arising from the use of this software. |
| 7 | + * |
| 8 | + * Permission is granted to anyone to use this software for any purpose, |
| 9 | + * including commercial applications, and to alter it and redistribute it |
| 10 | + * freely, subject to the following restrictions: |
| 11 | + * |
| 12 | + * 1. The origin of this software must not be misrepresented; you must not |
| 13 | + * claim that you wrote the original software. If you use this software |
| 14 | + * in a product, an acknowledgment in the product documentation would be |
| 15 | + * appreciated but is not required. |
| 16 | + * 2. Altered source versions must be plainly marked as such, and must not be |
| 17 | + * misrepresented as being the original software. |
| 18 | + * 3. This notice may not be removed or altered from any source distribution. |
| 19 | + * |
| 20 | + * Joe Ranieri joe@alacatia.com |
| 21 | + * |
| 22 | + */ |
| 23 | + |
| 24 | +// |
| 25 | +// Updated by Robert Widmann. |
| 26 | +// Copyright © 2015 CodaFi. All rights reserved. |
| 27 | +// Released under the MIT license. |
| 28 | +// |
| 29 | + |
| 30 | +#ifndef CGS_CONNECTION_INTERNAL_H |
| 31 | +#define CGS_CONNECTION_INTERNAL_H |
| 32 | + |
| 33 | +/// The type of connections to the Window Server. |
| 34 | +/// |
| 35 | +/// Every application is given a singular connection ID through which it can receieve and manipulate |
| 36 | +/// values, state, notifications, events, etc. in the Window Server. It |
| 37 | +typedef int CGSConnectionID; |
| 38 | + |
| 39 | +typedef void *CGSNotificationData; |
| 40 | +typedef void *CGSNotificationArg; |
| 41 | +typedef int CGSTransitionID; |
| 42 | + |
| 43 | + |
| 44 | +#pragma mark - Connection Lifecycle |
| 45 | + |
| 46 | + |
| 47 | +/// Gets the default connection for this process. |
| 48 | +CG_EXTERN CGSConnectionID CGSMainConnectionID(void); |
| 49 | + |
| 50 | +/// Creates a new connection to the Window Server. |
| 51 | +CG_EXTERN CGError CGSNewConnection(int unused, CGSConnectionID *outConnection); |
| 52 | + |
| 53 | +/// Releases a CGSConnection and all CGSWindows owned by it. |
| 54 | +CG_EXTERN CGError CGSReleaseConnection(CGSConnectionID cid); |
| 55 | + |
| 56 | +/// Gets the default connection for the current thread. |
| 57 | +CG_EXTERN CGSConnectionID CGSDefaultConnectionForThread(void); |
| 58 | + |
| 59 | +/// Gets the pid of the process that owns this connection to the Window Server. |
| 60 | +CG_EXTERN CGError CGSConnectionGetPID(CGSConnectionID cid, pid_t *outPID); |
| 61 | + |
| 62 | +/// Gets the connection for the given process serial number. |
| 63 | +CG_EXTERN CGError CGSGetConnectionIDForPSN(CGSConnectionID cid, const ProcessSerialNumber *psn, CGSConnectionID *outOwnerCID); |
| 64 | + |
| 65 | +/// Returns whether the menu bar exists for the given connection ID. |
| 66 | +/// |
| 67 | +/// For the majority of applications, this function should return true. But at system updates, |
| 68 | +/// initialization, and shutdown, the menu bar will be either initially gone then created or |
| 69 | +/// hidden and then destroyed. |
| 70 | +CG_EXTERN bool CGSMenuBarExists(CGSConnectionID cid); |
| 71 | + |
| 72 | +/// Closes ALL connections to the Window Server by the current application. |
| 73 | +/// |
| 74 | +/// The application is effectively turned into a Console-based application after the invocation of |
| 75 | +/// this method. |
| 76 | +CG_EXTERN CGError CGSShutdownServerConnections(void); |
| 77 | + |
| 78 | + |
| 79 | +#pragma mark - Connection Properties |
| 80 | + |
| 81 | + |
| 82 | +/// Retrieves the value associated with the given key for the given connection. |
| 83 | +/// |
| 84 | +/// This method is structured so processes can send values through the Window Server to other |
| 85 | +/// processes - assuming they know each others connection IDs. The recommended use case for this |
| 86 | +/// function appears to be keeping state around for application-level sub-connections. |
| 87 | +CG_EXTERN CGError CGSCopyConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef *outValue); |
| 88 | + |
| 89 | +/// Associates a value for the given key on the given connection. |
| 90 | +CG_EXTERN CGError CGSSetConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef value); |
| 91 | + |
| 92 | + |
| 93 | +#pragma mark - Connection Updates |
| 94 | + |
| 95 | + |
| 96 | +/// Disables updates on a connection |
| 97 | +/// |
| 98 | +/// Calls to disable updates nest much like `-beginUpdates`/`-endUpdates`. the Window Server will |
| 99 | +/// forcibly reenable updates after 1 second if you fail to invoke `CGSReenableUpdate`. |
| 100 | +CG_EXTERN CGError CGSDisableUpdate(CGSConnectionID cid); |
| 101 | + |
| 102 | +/// Re-enables updates on a connection. |
| 103 | +/// |
| 104 | +/// Calls to enable updates nest much like `-beginUpdates`/`-endUpdates`. |
| 105 | +CG_EXTERN CGError CGSReenableUpdate(CGSConnectionID cid); |
| 106 | + |
| 107 | + |
| 108 | +#pragma mark - System-Level Notification Registration |
| 109 | + |
| 110 | + |
| 111 | +typedef enum { |
| 112 | + kCGSNotificationDebugOptionsChanged = 200, |
| 113 | + |
| 114 | + kCGSNotificationMouseMoved = 715, |
| 115 | + |
| 116 | + kCGSNotificationTrackingRegionEntered = 718, |
| 117 | + kCGSNotificationTrackingRegionExited = 719, |
| 118 | + |
| 119 | + // 724 - keyboard preferences changed |
| 120 | + |
| 121 | + // 729, 730 seem to be process deactivated / activated - but only for this process |
| 122 | + // 731 seems to be this process hidden or shown |
| 123 | + |
| 124 | + // kCGSNotificationAppUnresponsive = 750, |
| 125 | + // kCGSNotificationAppResponsive = 751, |
| 126 | + |
| 127 | + // 761 - hotkey disabled |
| 128 | + // 762 - hotkey enabled (do these two fire twice?) |
| 129 | + |
| 130 | + // 763 - hotkey begins editing |
| 131 | + // 764 - hotkey ends editing |
| 132 | + |
| 133 | + // 765, 766 seem to be about the hotkey state (all disabled, etc) |
| 134 | + |
| 135 | + kCGSNotificationWorkspaceChanged = 1401, |
| 136 | + |
| 137 | + kCGSNotificationTransitionEnded = 1700, |
| 138 | +} CGSNotificationType; |
| 139 | + |
| 140 | +typedef void (*CGSNotifyProcPtr)(CGSNotificationType type, void *data, unsigned int dataLength, void *userData); |
| 141 | + |
| 142 | +/// Registers a function to receive notifications for system-wide events. |
| 143 | +CG_EXTERN CGError CGSRegisterNotifyProc(CGSNotifyProcPtr proc, CGSNotificationType type, void *userData); |
| 144 | + |
| 145 | +/// Unregisters a function that was registered to receive notifications for system-wide events. |
| 146 | +CG_EXTERN CGError CGSRemoveNotifyProc(CGSNotifyProcPtr proc, CGSNotificationType type, void *userData); |
| 147 | + |
| 148 | + |
| 149 | +#pragma mark - Application-Level Notification Registration |
| 150 | + |
| 151 | + |
| 152 | +typedef enum { |
| 153 | + kCGSScreenResolutionChangedEvent = 100, |
| 154 | + kCGSScreenDisplayParametersChangedEvent = 101, |
| 155 | + kCGSClientEnterFullscreen = 106, |
| 156 | + kCGSClientExitFullscreen = 107, |
| 157 | + kCGSScreenAcceleratorChangedEvent = 121, |
| 158 | + kCGSNotificationAppUnresponsive = 750, |
| 159 | + kCGSNotificationAppResponsive = 751, |
| 160 | + kCGSWorkspaceConfigurationDisabledEvent = 761, |
| 161 | + kCGSWorkspaceConfigurationEnabledEvent = 762, |
| 162 | + kCGSWindowDidBecomeUnoccludedEvent = 912, |
| 163 | + kCGSWindowDidBecomeOccludedEvent = 913, |
| 164 | + kCGSWindowWasMovedByDockEvent = 1205, |
| 165 | + kCGSWindowWasResizedByDockEvent = 1207, |
| 166 | + kCGSWindowDidBecomeManagedByDockEvent = 1208, |
| 167 | + kCGSWindowTileSpaceBeganLiveResize = 1312, |
| 168 | + kCGSWindowTileSpaceEndedLiveResize = 1313, |
| 169 | + kCGSWindowTileSpaceDidResize = 1314, |
| 170 | + kCGSWorkspaceChangedEvent = 1401, |
| 171 | +} CGSConnectionNotifyEvent; |
| 172 | + |
| 173 | +typedef void (*CGConnectionNotifyProc)(CGSNotificationType type, CGSNotificationData notificationData, size_t dataLength, CGSNotificationArg userParameter, CGSConnectionID); |
| 174 | + |
| 175 | +/// Registers a function to receive notifications for connection-level events. |
| 176 | +CG_EXTERN CGError CGSRegisterConnectionNotifyProc(CGSConnectionID cid, CGConnectionNotifyProc function, CGSConnectionNotifyEvent event, void *userData); |
| 177 | + |
| 178 | +/// Unregisters a function that was registered to receive notifications for connection-level events. |
| 179 | +CG_EXTERN CGError CGSRemoveConnectionNotifyProc(CGSConnectionID cid, CGConnectionNotifyProc function, CGSConnectionNotifyEvent event, void *userData); |
| 180 | + |
| 181 | + |
| 182 | +typedef void (*CGSNewConnectionNotificationProc)(CGSConnectionID cid); |
| 183 | + |
| 184 | +/// Registers a function that gets invoked when the application's connection ID is created by the |
| 185 | +/// Window Server. |
| 186 | +CG_EXTERN CGError CGSRegisterForNewConnectionNotification(CGSNewConnectionNotificationProc proc); |
| 187 | + |
| 188 | +/// Removes a function that was registered to receive notifications for the creation of the |
| 189 | +/// application's connection to the Window Server. |
| 190 | +CG_EXTERN CGError CGSRemoveNewConnectionNotification(CGSNewConnectionNotificationProc proc); |
| 191 | + |
| 192 | +typedef void (*CGSConnectionDeathNotificationProc)(CGSConnectionID cid); |
| 193 | + |
| 194 | +/// Registers a function that gets invoked when the application's connection ID is destroyed - |
| 195 | +/// ideally by the Window Server. |
| 196 | +/// |
| 197 | +/// Connection death is supposed to be a fatal event that is only triggered when the application |
| 198 | +/// terminates or when you have explicitly destroyed a sub-connection to the Window Server. |
| 199 | +CG_EXTERN CGError CGSRegisterForConnectionDeathNotification(CGSConnectionDeathNotificationProc proc); |
| 200 | + |
| 201 | +/// Removes a function that was registered to receive notifications for the destruction of the |
| 202 | +/// application's connection to the Window Server. |
| 203 | +CG_EXTERN CGError CGSRemoveConnectionDeathNotification(CGSConnectionDeathNotificationProc proc); |
| 204 | + |
| 205 | + |
| 206 | +#pragma mark - Miscellaneous Security Holes |
| 207 | + |
| 208 | +/// Sets a "Universal Owner" for the connection ID. Currently, that owner is Dock.app, which needs |
| 209 | +/// control over the window to provide system features like hiding and showing windows, moving them |
| 210 | +/// around, etc. |
| 211 | +/// |
| 212 | +/// Because the Universal Owner owns every window under this connection, it can manipulate them |
| 213 | +/// all as it sees fit. If you can beat the dock, you have total control over the process' |
| 214 | +/// connection. |
| 215 | +CG_EXTERN CGError CGSSetUniversalOwner(CGSConnectionID cid); |
| 216 | + |
| 217 | +/// Assuming you have the connection ID of the current universal owner, or are said universal owner, |
| 218 | +/// allows you to specify another connection that has total control over the application's windows. |
| 219 | +CG_EXTERN CGError CGSSetOtherUniversalConnection(CGSConnectionID cid, CGSConnectionID otherConnection); |
| 220 | + |
| 221 | +/// Sets the given connection ID as the login window connection ID. Windows for the application are |
| 222 | +/// then brought to the fore when the computer logs off or goes to sleep. |
| 223 | +/// |
| 224 | +/// Why this is still here, I have no idea. Window Server only accepts one process calling this |
| 225 | +/// ever. If you attempt to invoke this after loginwindow does you will be yelled at and nothing |
| 226 | +/// will happen. If you can manage to beat loginwindow, however, you know what they say: |
| 227 | +/// |
| 228 | +/// When you teach a man to phish... |
| 229 | +CG_EXTERN CGError CGSSetLoginwindowConnection(CGSConnectionID cid) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; |
| 230 | + |
| 231 | +//! The data sent with kCGSNotificationAppUnresponsive and kCGSNotificationAppResponsive. |
| 232 | +typedef struct { |
| 233 | +#if __BIG_ENDIAN__ |
| 234 | + uint16_t majorVersion; |
| 235 | + uint16_t minorVersion; |
| 236 | +#else |
| 237 | + uint16_t minorVersion; |
| 238 | + uint16_t majorVersion; |
| 239 | +#endif |
| 240 | + |
| 241 | + //! The length of the entire notification. |
| 242 | + uint32_t length; |
| 243 | + |
| 244 | + CGSConnectionID cid; |
| 245 | + pid_t pid; |
| 246 | + ProcessSerialNumber psn; |
| 247 | +} CGSProcessNotificationData; |
| 248 | + |
| 249 | +//! The data sent with kCGSNotificationDebugOptionsChanged. |
| 250 | +typedef struct { |
| 251 | + int newOptions; |
| 252 | + int unknown[2]; // these two seem to be zero |
| 253 | +} CGSDebugNotificationData; |
| 254 | + |
| 255 | +//! The data sent with kCGSNotificationTransitionEnded |
| 256 | +typedef struct { |
| 257 | + CGSTransitionID transition; |
| 258 | +} CGSTransitionNotificationData; |
| 259 | + |
| 260 | +#endif /* CGS_CONNECTION_INTERNAL_H */ |
0 commit comments