Notification icons specified with a GUID are protected against spoofing by validating that only a single application registers them. This registration is performed the first time you call Shell_NotifyIcon(NIM_ADD, …) and the full path name of the calling application is stored. If you later move your binary file to a different location, the system will not allow the icon to be added again.
TLDR if you know the guid to a systray icon, you can hijack and control any systray icon from a different app - arguably the complete opposite of the spoofing claim in the link above!!!
To display an icon in the system tray a handle to an icon needs to be provided.
A single app can have one or more icons visible in the systray.
Each systray instance displaying an icon can also share a single window handle & callback procedure or have its own window handle and callback procedure to intercept and process windows messages generated by the user interacting with the corresponding systray icon.
Upto Win7 the uID in the NOTIFYICONDATAA (shellapi.h) - Win32 apps | Microsoft Learn is the unique identifier used to control a systray icon or the space where an icon would appear because its not mandatory to display an icon!
Win7 onwards, the GuidItem is recommended for use to control the systray icons, although the uID will still work on Win10 if no guiditem is specified, I guess for backwards compatibility reasons.
So I dont really see what the Guiditem brings to the table from Win7 onwards, other than it prevents an app which has the guiditem hard coded in the app from being moved from one folder to another.
If your app does use the same guid and you try to move it or copy it to a different location, a windows error will get thrown: namely 2147500037 which doesnt appear in this list of windows error codes Tutorial - Debug system error codes - Win32 apps | Microsoft Learn as the last windows error code is
ERROR_API_UNAVAILABLE - 15841 (0x3DE1) - This API cannot be used in the context of the caller’s application type.
As it happens my apps generate a new guid everytime it loads the icons from various sources, so the user can move an app to a different location and also choose what icons are used in the systray.
So apart from providing a stealth way of preventing an app being moved to a different folder if it happens to use the same “hardcoded” guid and systray icon, I cant see the purpose of this functionality.
Likwise, another app using only the same guid can control the systray icons from the 1st app, in other words its possible to hijack a systray icon if you know its guid which is the opposite of whats being claimed in the 1st MS link.
It seems all thats needed is knowledge of the guid, they dont even need the same handles to icons and windows or callback procedure addresses in order to hijack the systray icons on display, and then play with users!
So does anyone know why this guiditem is now recommend use?
So its also possible to hijack the systray icons using the old hwnd + uID way. All it needs is matching hwnd and uid and you can take control of the systray icon. Interestingly, the NOTIFYICONDATA can even have different memory locations, from different exe’s to control the user notifications.
So next test is to see what else I can get the systray notifications to do…
Its also an insight into how joined up or not this api is with other parts of the OS.
One other implication is, its really easy scanning exe’s and dll’s for guid’s using a regex unlike getting a runtime api assigned handle and uID, but there is nothing stopping us from using a new guid everytime an icon is loaded from the exe/dll resource section, or from other file locations.
Either way, its possible to have some fun with these window notification popup messages for other apps running in the systray.