private static Native.TBBUTTON32 ConvertToTBButton32(object obj)
        {
            if (obj is Native.TBBUTTON32)
            {
                return((Native.TBBUTTON32)obj);
            }

            Native.TBBUTTON64 tbb64 = (Native.TBBUTTON64)obj;
            return(new Native.TBBUTTON32
            {
                dwData = tbb64.dwData,
                fsState = tbb64.fsState,
                fsStyle = tbb64.fsStyle,
                iBitmap = tbb64.iBitmap,
                idCommand = tbb64.idCommand,
                iString = tbb64.iString
            });
        }
        /// <summary>
        /// Get information about all icons
        /// </summary>
        public static List <NotificationIconInfo> GetVisibleIcons()
        {
            try
            {
                var toolbarWindow = GetUserToolbar();
                var result        = new List <NotificationIconInfo>();
                if (toolbarWindow.Handle == IntPtr.Zero)
                {
                    return(result);
                }

                int count = (int)Native.SendMessage(toolbarWindow.Handle, (uint)Native.WindowMessage.TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero);
                if (count == 0)
                {
                    return(result);
                }

                uint pid;
                Native.GetWindowThreadProcessId(toolbarWindow.Handle, out pid);

                bool   hr;
                IntPtr hproc = IPCNative.OpenProcess(IPCNative.ProcessAccess.AllAccess, false, (int)pid);

                for (int i = 0; i < count; i++)
                {
                    int sizeOfTbButton = Marshal.SizeOf(Is64Bits() ? typeof(Native.TBBUTTON64) : typeof(Native.TBBUTTON32));

                    // Allocate memory for TBBUTTON structure
                    IntPtr pTBBUTTON = IPCNative.VirtualAllocEx(hproc, IntPtr.Zero, (uint)sizeOfTbButton,
                                                                IPCNative.AllocationType.Commit, IPCNative.MemoryProtection.ReadWrite);

                    // Ask explorer.exe to fill the structure we just allocated
                    Native.SendMessage(toolbarWindow.Handle, (uint)Native.WindowMessage.TB_GETBUTTON, new IntPtr(i), pTBBUTTON);

                    // Read the structure from explorer.exe's memory
                    int    read;
                    object obj;
                    if (Is64Bits())
                    {
                        obj = new Native.TBBUTTON64();
                    }
                    else
                    {
                        obj = new Native.TBBUTTON32();
                    }
                    hr = IPCNative.ReadProcessMemory(hproc, pTBBUTTON, obj, sizeOfTbButton, out read);
                    Native.TBBUTTON32 tbbutton = ConvertToTBButton32(obj);

                    hr = IPCNative.VirtualFreeEx(hproc, pTBBUTTON, sizeOfTbButton, IPCNative.FreeType.Decommit | IPCNative.FreeType.Release);

                    // Get data associated with icon
                    IntPtr data = new IntPtr((int)tbbutton.dwData);

                    obj = new Native.SysTrayData();
                    IPCNative.ReadProcessMemory(hproc, data, obj, Marshal.SizeOf(typeof(Native.SysTrayData)), out read);
                    Native.SysTrayData trayData = (Native.SysTrayData)obj;

                    FixTrayDataAnyCPU(ref trayData);

                    if (trayData.wParam < 0)
                    {
                        continue;
                    }

                    // Get tooltip length
                    int size = (int)Native.SendMessage(toolbarWindow.Handle, (uint)Native.WindowMessage.TB_GETBUTTONTEXT, (IntPtr)tbbutton.idCommand, IntPtr.Zero);
                    size *= 2; // because it is unicode

                    // Alloc memory for explorer.exe to write tooltip to
                    IntPtr pText = IPCNative.VirtualAllocEx(hproc, IntPtr.Zero, (uint)size, IPCNative.AllocationType.Commit, IPCNative.MemoryProtection.ReadWrite);
                    Native.SendMessage(toolbarWindow.Handle, (uint)Native.WindowMessage.TB_GETBUTTONTEXT, (IntPtr)tbbutton.idCommand, pText);

                    // Read tooltip from memory
                    byte[] objstr = new byte[size];
                    IPCNative.ReadProcessMemory(hproc, pText, objstr, size, out read);

                    hr = IPCNative.VirtualFreeEx(hproc, pText, size, IPCNative.FreeType.Decommit | IPCNative.FreeType.Release);

                    string tooltip = UnicodeEncoding.Unicode.GetString(objstr);

                    NotificationIconInfo icon = new NotificationIconInfo
                    {
                        BitmapIndex    = tbbutton.iBitmap,
                        DataIdentifier = tbbutton.dwData,
                        Data           = trayData,
                        Tooltip        = tooltip
                    };

                    result.Add(icon);
                }

                hr = IPCNative.CloseHandle(hproc);

                return(result);
            }
            catch (OverflowException)
            {
                return(new List <NotificationIconInfo>());
            }
        }