Geoff Chappell - Software Analyst
Each of the SHAppBarMessage, Shell_NotifyIcon, SHEnableServiceObject and SHLoadInProc functions is little more than a gateway for sending data to the taskbar window (and in some few cases, getting data back). The packaging of this data and the methods of its transmission are implementation details, but have much in common across the functions.
The calling process is typically not the process that implements the taskbar window. The standard method of passing data to a window function in another process is with the dwData member of the COPYDATASTRUCT and/or an arbitrary amount in a buffer described by the lpData and cbData members. SHELL32 passes both. The DWORD serves to identify which function the data in the buffer is being passed for:message. This provides for passing a DWORD in the
|2||SHEnableServiceObject or SHLoadInProc|
The buffer layout for SHAppBarMessage is:
|0x00||0x28 bytes||enhanced APPBARDATA structure, with cbSize set to 0x28 and lParam sign-extended to QWORD|
|0x2C||dword||handle to a copy of the enhanced APPBARDATA in shared memory, else NULL|
|0x30||dword||process ID of caller|
|0x34||0x04 bytes||unused, presumed to be padding from QWORD alignment|
The point to the shared memory and process ID is that for some values of dwMessage, the SHAppBarMessage function is expected to return information in members of the APPBARDATA structure. However, the mechanism copies data only from the source to the taskbar window, without providing a means to write back. The solution found by SHELL32 is that in the cases where it is needed, the enhanced APPBARDATA that is anyway passed in the buffer is also copied to shared memory and the means for accessing this shared memory is also passed in the buffer.
For Shell_NotifyIcon, the data for the buffer is laid out as follows. In the symbol file for EXPLORER.EXE, Microsoft publishes a name for this otherwise undocumented structure: TRAYNOTIFYDATAW.
|0x08||0x03B8 bytes||NOTIFYICONDATAW structure in current layout, constructed on stack from input at lpdata|
The SHEnableServiceObject and SHLoadInProc functions reduce to one operation differentiated by flags. The buffer layout is:
|0x00||0x10 bytes||CLSID from rclsid argument|
|0x10||dword||0x01 for SHLoadInProc
0x02 for SHEnableServiceObject if fEnable argument is FALSE
0x03 for SHEnableServiceObject if fEnable argument is non-zero