Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set application name in macOS driver #9

Open
wants to merge 6 commits into
base: 7.7
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions dlls/winemac.drv/cocoa_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ enum {
WineApplicationEventWakeQuery,
};

/* Whisky hack #9 */
#define kAppNameText @"%@ (Whi" \
@"sky)"


@class WineEventQueue;
@class WineWindow;
Expand Down Expand Up @@ -128,6 +132,8 @@ enum {

NSImage* applicationIcon;

NSString* applicationName; /* Whisky hack #9 */

BOOL beenActive;

NSMutableSet* windowsBeingDragged;
Expand Down
137 changes: 137 additions & 0 deletions dlls/winemac.drv/cocoa_app.m
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ @interface WineApplicationController ()
@property (retain, nonatomic) NSTimer* cursorTimer;
@property (retain, nonatomic) NSCursor* cursor;
@property (retain, nonatomic) NSImage* applicationIcon;
@property (copy, nonatomic) NSString* applicationName; /* Whisky hack #9 */
@property (readonly, nonatomic) BOOL inputSourceIsInputMethod;
@property (retain, nonatomic) WineWindow* mouseCaptureWindow;

Expand All @@ -108,6 +109,7 @@ @implementation WineApplicationController
@synthesize keyboardType, lastFlagsChanged;
@synthesize displaysTemporarilyUncapturedForDialog, temporarilyIgnoreResignEventsForDialog;
@synthesize applicationIcon;
@synthesize applicationName; /* Whisky hack #9 */
@synthesize cursorFrames, cursorTimer, cursor;
@synthesize mouseCaptureWindow;
@synthesize lastSetCursorPositionTime;
Expand Down Expand Up @@ -201,6 +203,7 @@ - (void) dealloc
[cursor release];
[screenFrameCGRects release];
[applicationIcon release];
[applicationName release]; /* Whisky hack #9 */
[clipCursorHandler release];
[cursorTimer release];
[cursorFrames release];
Expand Down Expand Up @@ -384,6 +387,13 @@ - (void) transformProcessToForeground:(BOOL)activateIfTransformed
[self changeEditMenuKeyEquivalentsForWindow:[NSApp keyWindow]];

[NSApp setApplicationIconImage:self.applicationIcon];

/* Whisky hack #9 */
// Set application name
NSString* appName = [NSString stringWithFormat:kAppNameText, self.applicationName];
bool success = [self setProcessName:appName];
if (!success)
NSLog(@"Failed to set process name to %@", appName);
}
}

Expand Down Expand Up @@ -833,6 +843,110 @@ - (void) sendDisplaysChanged:(BOOL)activating
macdrv_release_event(event);
}

/* Whisky hack #9 */
- (BOOL) setProcessName:(NSString*)name
{
// Convert the name to a CFString
CFStringRef cfName = (CFStringRef)name;

// Must be called on the main thread
if (![NSThread isMainThread]) {
NSLog(@"setProcessName: must be called on the main thread");
return false;
}

// New name can't be NULL or empty
if (!cfName || CFStringGetLength(cfName) == 0) {
NSLog(@"setProcessName: Invalid process name");
return false;
}

// Private types used in calls to launch services
typedef CFTypeRef PrivateLaunchRef;
typedef PrivateLaunchRef (*LSGetCurrentApplicationASNType)(void);
typedef OSStatus (*LSSetApplicationInformationItemType)(
int,
PrivateLaunchRef,
CFStringRef,
CFStringRef,
CFDictionaryRef
);

// Static so we can reuse the same function pointers
static bool initialized = false;
static LSGetCurrentApplicationASNType getCurrentAppASNFunc = NULL;
static LSSetApplicationInformationItemType setAppInfoFunc = NULL;
static CFStringRef launchServicesDisplayNameKey = NULL;

// Initialize the function pointers
if (!initialized) {
initialized = true;

// Get the bundle for the LaunchServices framework
CFBundleRef launchServicesBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
if (!launchServicesBundle) {
NSLog(@"setProcessName: Failed to get LaunchServices bundle");
return false;
}

// Get the function pointers
getCurrentAppASNFunc = (LSGetCurrentApplicationASNType)(
CFBundleGetFunctionPointerForName(launchServicesBundle, CFSTR("_LSGetCurrentApplicationASN"))
);
if (!getCurrentAppASNFunc) {
NSLog(@"setProcessName: Failed to get _LSGetCurrentApplicationASN in LaunchServices");
return false;
}
setAppInfoFunc = (LSSetApplicationInformationItemType)(
CFBundleGetFunctionPointerForName(launchServicesBundle, CFSTR("_LSSetApplicationInformationItem"))
);
if (!setAppInfoFunc) {
NSLog(@"setProcessName: Failed to get _LSSetApplicationInformationItem in LaunchServices");
return false;
}

// Get the display name key
const CFStringRef* displayNameKey = (const CFStringRef*)(
CFBundleGetDataPointerForName(launchServicesBundle, CFSTR("_kLSDisplayNameKey"))
);
launchServicesDisplayNameKey = displayNameKey ? *displayNameKey : NULL;
if (!launchServicesDisplayNameKey) {
NSLog(@"setProcessName: Failed to get _kLSDisplayNameKey in LaunchServices");
return false;
}

// Force symbols to be loaded in the LaunchServices framework
ProcessSerialNumber psn = {0, kCurrentProcess};
GetCurrentProcess(&psn);
}

// If any of the function pointers are NULL, we can't continue
if (!getCurrentAppASNFunc || !setAppInfoFunc || !launchServicesDisplayNameKey) {
NSLog(@"setProcessName: Failed to get all required LaunchServices functions");
return false;
}

// Get the current application's ASN
PrivateLaunchRef currentAppASN = getCurrentAppASNFunc();

// Set the display name
OSErr err = setAppInfoFunc(
-2, // WebKit uses -2
currentAppASN,
launchServicesDisplayNameKey,
cfName,
NULL // Output parameter
);

// Log any errors
if (err != noErr) {
NSLog(@"setProcessName: Failed to set display name: %d", err);
return false;
}

return true;
}

// We can compare two modes directly using CFEqual, but that may require that
// they are identical to a level that we don't need. In particular, when the
// OS switches between the integrated and discrete GPUs, the set of display
Expand Down Expand Up @@ -1176,6 +1290,13 @@ - (void) setApplicationIconFromCGImageArray:(NSArray*)images
self.applicationIcon = nsimage;
}

/* Whisky hack #9 */
- (void) setApplicationName:(NSString*)name
{
[applicationName release];
applicationName = [name copy];
}

- (void) handleCommandTab
{
if ([NSApp isActive])
Expand Down Expand Up @@ -2634,6 +2755,22 @@ void macdrv_set_application_icon(CFArrayRef images, CFURLRef urlRef)
});
}

/* Whisky hack #9 */
/***********************************************************************
* macdrv_set_application_name
*
* Set the application name.
*/
void macdrv_set_application_name(CFStringRef name)
{
NSString* nsName = (NSString*)name;

OnMainThreadAsync(^{
WineApplicationController* controller = [WineApplicationController sharedController];
[controller setApplicationName:nsName];
});
}

/***********************************************************************
* macdrv_quit_reply
*/
Expand Down
1 change: 1 addition & 0 deletions dlls/winemac.drv/macdrv_cocoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN;
extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN;
extern void macdrv_beep(void) DECLSPEC_HIDDEN;
extern void macdrv_set_application_icon(CFArrayRef images, CFURLRef url /* CrossOver Hack 13440 */) DECLSPEC_HIDDEN;
extern void macdrv_set_application_name(CFStringRef name) DECLSPEC_HIDDEN; /* Whisky hack #9 */
extern void macdrv_quit_reply(int reply) DECLSPEC_HIDDEN;
extern int macdrv_using_input_method(void) DECLSPEC_HIDDEN;
extern void macdrv_set_mouse_capture_window(macdrv_window window) DECLSPEC_HIDDEN;
Expand Down
30 changes: 30 additions & 0 deletions dlls/winemac.drv/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,34 @@ static void set_app_icon(void)
}
}

/* Whisky hack #9 */
/***********************************************************************
* set_app_name
*/
static void set_app_name(void)
{
WCHAR app_name[MAX_PATH];
DWORD len = GetModuleFileNameW(0, app_name, ARRAY_SIZE(app_name));

// Get offset to the last backslash
DWORD last_char_pos = 0;
for (DWORD i = 0; i < len; i++)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iterating backward will give the same result without multiple reassignments

{
if (app_name[i] == '\\')
last_char_pos = i;
}

if (len && len < ARRAY_SIZE(app_name))
Copy link

@gennady-lebedev gennady-lebedev Aug 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for-loop up above will also fail if this condition is false

possible OOB vulnerability

{
CFStringRef name = CFStringCreateWithCharacters(NULL, app_name + last_char_pos + 1, len - last_char_pos - 1);
if (name)
{
macdrv_set_application_name(name);
CFRelease(name);
}
}
}


/**********************************************************************
* set_capture_window_for_move
Expand Down Expand Up @@ -1661,6 +1689,8 @@ BOOL macdrv_CreateDesktopWindow(HWND hwnd)
}

set_app_icon();
/* Whisky hack #9 */
set_app_name();
return TRUE;
}

Expand Down